blob: 10eee6d466aa9fe3835e1cdc3b2db12ca1b57988 [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
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065/**
66 * @brief Updates the Functional State of DIMMs
67 *
Ed Tanousac106bf2023-06-07 09:24:59 -070068 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050069 * @param[in] dimmState Dimm's Functional state, true/false
70 *
71 * @return None.
72 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040073inline void updateDimmProperties(
74 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050075{
Ed Tanous62598e32023-07-17 17:06:25 -070076 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050077
Gunnar Mills4e0453b2020-07-08 14:00:30 -050078 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050079 // Update STATE only if previous State was DISABLED and current Dimm is
80 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070081 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070082 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050083 if (prevMemSummary == "Disabled")
84 {
Ed Tanouse05aec52022-01-25 10:28:56 -080085 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050086 {
Ed Tanousac106bf2023-06-07 09:24:59 -070087 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050088 "Enabled";
89 }
90 }
91}
92
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050094 * @brief Update "ProcessorSummary" "Status" "State" based on
95 * CPU Functional State
96 *
Ed Tanousac106bf2023-06-07 09:24:59 -070097 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050098 * @param[in] cpuFunctionalState is CPU functional true/false
99 *
100 * @return None.
101 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700102inline void modifyCpuFunctionalState(
103 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500104{
Ed Tanous62598e32023-07-17 17:06:25 -0700105 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106
Ed Tanous02cad962022-06-30 16:50:15 -0700107 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700108 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500109
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500110 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500111 // Update STATE only if previous State was Non_Functional and current CPU is
112 // Functional.
113 if (prevProcState == "Disabled")
114 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800115 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500116 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700117 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 "Enabled";
119 }
120 }
121}
122
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500123/*
124 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
125 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700126 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500127 * @param[in] cpuPresenceState CPU present or not
128 *
129 * @return None.
130 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400131inline void modifyCpuPresenceState(
132 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuPresent)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500133{
Ed Tanous62598e32023-07-17 17:06:25 -0700134 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500135
136 if (isCpuPresent)
137 {
138 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700139 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500140 auto* procCountPtr =
141 procCount.get_ptr<nlohmann::json::number_integer_t*>();
142 if (procCountPtr != nullptr)
143 {
144 // shouldn't be possible to be nullptr
145 *procCountPtr += 1;
146 }
147 }
148}
149
Ali Ahmed382d6472021-09-03 16:53:53 -0500150inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700151 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500152 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
153 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500154{
Ed Tanous62598e32023-07-17 17:06:25 -0700155 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500156
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200157 // TODO: Get Model
158
159 const uint16_t* coreCount = nullptr;
160
161 const bool success = sdbusplus::unpackPropertiesNoThrow(
162 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
163
164 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700166 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200167 return;
168 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500169
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200170 if (coreCount != nullptr)
171 {
172 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700173 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200174 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500175
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200176 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500177 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200178 coreCountJson = *coreCount;
179 }
180 else
181 {
182 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500183 }
184 }
185}
186
187/*
188 * @brief Get ProcessorSummary fields
189 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700190 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500191 * @param[in] service dbus service for Cpu Information
192 * @param[in] path dbus path for Cpu
193 *
194 * @return None.
195 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500196inline void getProcessorSummary(
197 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
198 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500199{
Ed Tanousac106bf2023-06-07 09:24:59 -0700200 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
201 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500202 if (ec3)
203 {
Ed Tanous62598e32023-07-17 17:06:25 -0700204 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500205 return;
206 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700207 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500208 };
209
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500210 // Get the Presence of CPU
Ed Tanousdeae6a72024-11-11 21:58:57 -0800211 dbus::utility::getProperty<bool>(*crow::connections::systemBus, service,
212 path, "xyz.openbmc_project.Inventory.Item",
213 "Present", std::move(getCpuPresenceState));
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500214
Ed Tanousdeae6a72024-11-11 21:58:57 -0800215 dbus::utility::getAllProperties(
216 service, path, "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700217 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800218 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800219 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400220 if (ec2)
221 {
222 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
223 messages::internalError(asyncResp->res);
224 return;
225 }
226 getProcessorProperties(asyncResp, properties);
227 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500228}
229
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500230/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500231 * @brief processMemoryProperties fields
232 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700233 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500234 * @param[in] DBUS properties for memory
235 *
236 * @return None.
237 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500238inline void processMemoryProperties(
239 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
240 const dbus::utility::DBusPropertiesMap& properties)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500241{
Ed Tanous62598e32023-07-17 17:06:25 -0700242 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500243
244 if (properties.empty())
245 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500246 return;
247 }
248
249 const size_t* memorySizeInKB = nullptr;
250
251 const bool success = sdbusplus::unpackPropertiesNoThrow(
252 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
253 memorySizeInKB);
254
255 if (!success)
256 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700257 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500258 return;
259 }
260
261 if (memorySizeInKB != nullptr)
262 {
263 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700264 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500265 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500266 if (preValue == nullptr)
267 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700268 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500269 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500270 }
271 else
272 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700273 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500274 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
275 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500276 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500277 }
278}
279
280/*
281 * @brief Get getMemorySummary fields
282 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700283 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500284 * @param[in] service dbus service for memory Information
285 * @param[in] path dbus path for memory
286 *
287 * @return None.
288 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500289inline void getMemorySummary(
290 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
291 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500292{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800293 dbus::utility::getAllProperties(
294 service, path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700295 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500296 path](const boost::system::error_code& ec2,
297 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400298 if (ec2)
299 {
300 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
301 messages::internalError(asyncResp->res);
302 return;
303 }
304 processMemoryProperties(asyncResp, properties);
305 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500306}
307
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500308inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
309 const boost::system::error_code& ec,
310 const dbus::utility::DBusPropertiesMap& properties)
311{
312 if (ec)
313 {
314 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
315 messages::internalError(asyncResp->res);
316 return;
317 }
318 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
319
320 const std::string* uUID = nullptr;
321
322 const bool success = sdbusplus::unpackPropertiesNoThrow(
323 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
324
325 if (!success)
326 {
327 messages::internalError(asyncResp->res);
328 return;
329 }
330
331 if (uUID != nullptr)
332 {
333 std::string valueStr = *uUID;
334 if (valueStr.size() == 32)
335 {
336 valueStr.insert(8, 1, '-');
337 valueStr.insert(13, 1, '-');
338 valueStr.insert(18, 1, '-');
339 valueStr.insert(23, 1, '-');
340 }
341 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
342 asyncResp->res.jsonValue["UUID"] = valueStr;
343 }
344}
345
Patrick Williams504af5a2025-02-03 14:29:03 -0500346inline void afterGetInventory(
347 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
348 const boost::system::error_code& ec,
349 const dbus::utility::DBusPropertiesMap& propertiesList)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500350{
351 if (ec)
352 {
353 // doesn't have to include this
354 // interface
355 return;
356 }
357 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
358
359 const std::string* partNumber = nullptr;
360 const std::string* serialNumber = nullptr;
361 const std::string* manufacturer = nullptr;
362 const std::string* model = nullptr;
363 const std::string* subModel = nullptr;
364
365 const bool success = sdbusplus::unpackPropertiesNoThrow(
366 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
367 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
368 "Model", model, "SubModel", subModel);
369
370 if (!success)
371 {
372 messages::internalError(asyncResp->res);
373 return;
374 }
375
376 if (partNumber != nullptr)
377 {
378 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
379 }
380
381 if (serialNumber != nullptr)
382 {
383 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
384 }
385
386 if (manufacturer != nullptr)
387 {
388 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
389 }
390
391 if (model != nullptr)
392 {
393 asyncResp->res.jsonValue["Model"] = *model;
394 }
395
396 if (subModel != nullptr)
397 {
398 asyncResp->res.jsonValue["SubModel"] = *subModel;
399 }
400
401 // Grab the bios version
402 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
403 "BiosVersion", false);
404}
405
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400406inline void afterGetAssetTag(
407 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
408 const boost::system::error_code& ec, const std::string& value)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500409{
410 if (ec)
411 {
412 // doesn't have to include this
413 // interface
414 return;
415 }
416
417 asyncResp->res.jsonValue["AssetTag"] = value;
418}
419
420inline void afterSystemGetSubTree(
421 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500422 const boost::system::error_code& ec,
423 const dbus::utility::MapperGetSubTreeResponse& subtree)
424{
425 if (ec)
426 {
427 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
428 messages::internalError(asyncResp->res);
429 return;
430 }
431 // Iterate over all retrieved ObjectPaths.
432 for (const std::pair<
433 std::string,
434 std::vector<std::pair<std::string, std::vector<std::string>>>>&
435 object : subtree)
436 {
437 const std::string& path = object.first;
438 BMCWEB_LOG_DEBUG("Got path: {}", path);
439 const std::vector<std::pair<std::string, std::vector<std::string>>>&
440 connectionNames = object.second;
441 if (connectionNames.empty())
442 {
443 continue;
444 }
445
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500446 // This is not system, so check if it's cpu, dimm, UUID or
447 // BiosVer
448 for (const auto& connection : connectionNames)
449 {
450 for (const auto& interfaceName : connection.second)
451 {
452 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
453 {
454 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
455
456 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500457 }
458 else if (interfaceName ==
459 "xyz.openbmc_project.Inventory.Item.Cpu")
460 {
461 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
462
463 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500464 }
465 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
466 {
467 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
468
Ed Tanousdeae6a72024-11-11 21:58:57 -0800469 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500470 *crow::connections::systemBus, connection.first, path,
471 "xyz.openbmc_project.Common.UUID",
472 [asyncResp](const boost::system::error_code& ec3,
473 const dbus::utility::DBusPropertiesMap&
474 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400475 afterGetUUID(asyncResp, ec3, properties);
476 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500477 }
478 else if (interfaceName ==
479 "xyz.openbmc_project.Inventory.Item.System")
480 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800481 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500482 *crow::connections::systemBus, connection.first, path,
483 "xyz.openbmc_project.Inventory.Decorator.Asset",
484 [asyncResp](const boost::system::error_code& ec3,
485 const dbus::utility::DBusPropertiesMap&
486 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400487 afterGetInventory(asyncResp, ec3, properties);
488 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500489
Ed Tanousdeae6a72024-11-11 21:58:57 -0800490 dbus::utility::getProperty<std::string>(
491 connection.first, path,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500492 "xyz.openbmc_project.Inventory.Decorator."
493 "AssetTag",
494 "AssetTag",
495 std::bind_front(afterGetAssetTag, asyncResp));
496 }
497 }
498 }
499 }
500}
501
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500502/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700503 * @brief Retrieves computer system properties over dbus
504 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700505 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700506 *
507 * @return None.
508 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500509inline void getComputerSystem(
510 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700511{
Ed Tanous62598e32023-07-17 17:06:25 -0700512 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800513 constexpr std::array<std::string_view, 5> interfaces = {
514 "xyz.openbmc_project.Inventory.Decorator.Asset",
515 "xyz.openbmc_project.Inventory.Item.Cpu",
516 "xyz.openbmc_project.Inventory.Item.Dimm",
517 "xyz.openbmc_project.Inventory.Item.System",
518 "xyz.openbmc_project.Common.UUID",
519 };
520 dbus::utility::getSubTree(
521 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500522 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700523}
524
525/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700526 * @brief Retrieves host state properties over dbus
527 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200529 * @param[in] computerSystemIndex Index associated with the requested system
Ed Tanous6c34de42018-08-29 13:37:36 -0700530 *
531 * @return None.
532 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200533inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
534 const uint64_t computerSystemIndex)
Ed Tanous6c34de42018-08-29 13:37:36 -0700535{
Ed Tanous62598e32023-07-17 17:06:25 -0700536 BMCWEB_LOG_DEBUG("Get host information.");
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200537
Ed Tanousdeae6a72024-11-11 21:58:57 -0800538 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200539 getHostStateServiceName(computerSystemIndex),
540 getHostStateObjectPath(computerSystemIndex),
Ed Tanousdeae6a72024-11-11 21:58:57 -0800541 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700542 [asyncResp](const boost::system::error_code& ec,
543 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400544 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700545 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400546 if (ec == boost::system::errc::host_unreachable)
547 {
548 // Service not available, no error, just don't return
549 // host state info
550 BMCWEB_LOG_DEBUG("Service not available {}", ec);
551 return;
552 }
553 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
554 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700555 return;
556 }
Ed Tanous66173382018-08-15 18:20:59 -0700557
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400558 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
559 // Verify Host State
560 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
561 {
562 asyncResp->res.jsonValue["PowerState"] =
563 resource::PowerState::On;
564 asyncResp->res.jsonValue["Status"]["State"] =
565 resource::State::Enabled;
566 }
567 else if (hostState ==
568 "xyz.openbmc_project.State.Host.HostState.Quiesced")
569 {
570 asyncResp->res.jsonValue["PowerState"] =
571 resource::PowerState::On;
572 asyncResp->res.jsonValue["Status"]["State"] =
573 resource::State::Quiesced;
574 }
575 else if (hostState ==
576 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
577 {
578 asyncResp->res.jsonValue["PowerState"] =
579 resource::PowerState::On;
580 asyncResp->res.jsonValue["Status"]["State"] =
581 resource::State::InTest;
582 }
583 else if (
584 hostState ==
585 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
586 {
587 asyncResp->res.jsonValue["PowerState"] =
588 resource::PowerState::PoweringOn;
589 asyncResp->res.jsonValue["Status"]["State"] =
590 resource::State::Starting;
591 }
592 else if (
593 hostState ==
594 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
595 {
596 asyncResp->res.jsonValue["PowerState"] =
597 resource::PowerState::PoweringOff;
598 asyncResp->res.jsonValue["Status"]["State"] =
599 resource::State::Disabled;
600 }
601 else
602 {
603 asyncResp->res.jsonValue["PowerState"] =
604 resource::PowerState::Off;
605 asyncResp->res.jsonValue["Status"]["State"] =
606 resource::State::Disabled;
607 }
608 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700609}
610
611/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500612 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530613 *
614 * @param[in] dbusSource The boot source in DBUS speak.
615 *
616 * @return Returns as a string, the boot source in Redfish terms. If translation
617 * cannot be done, returns an empty string.
618 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000619inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530620{
621 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
622 {
623 return "None";
624 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700625 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530626 {
627 return "Hdd";
628 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700629 if (dbusSource ==
630 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530631 {
632 return "Cd";
633 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700634 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530635 {
636 return "Pxe";
637 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700638 if (dbusSource ==
639 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700640 {
641 return "Usb";
642 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700643 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530644}
645
646/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300647 * @brief Translates boot type DBUS property value to redfish.
648 *
649 * @param[in] dbusType The boot type in DBUS speak.
650 *
651 * @return Returns as a string, the boot type in Redfish terms. If translation
652 * cannot be done, returns an empty string.
653 */
654inline std::string dbusToRfBootType(const std::string& dbusType)
655{
656 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
657 {
658 return "Legacy";
659 }
660 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
661 {
662 return "UEFI";
663 }
664 return "";
665}
666
667/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500668 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530669 *
670 * @param[in] dbusMode The boot mode in DBUS speak.
671 *
672 * @return Returns as a string, the boot mode in Redfish terms. If translation
673 * cannot be done, returns an empty string.
674 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000675inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530676{
677 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
678 {
679 return "None";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530682 {
683 return "Diags";
684 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700685 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686 {
687 return "BiosSetup";
688 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700689 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530690}
691
692/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600693 * @brief Translates boot progress DBUS property value to redfish.
694 *
695 * @param[in] dbusBootProgress The boot progress in DBUS speak.
696 *
697 * @return Returns as a string, the boot progress in Redfish terms. If
698 * translation cannot be done, returns "None".
699 */
700inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
701{
702 // Now convert the D-Bus BootProgress to the appropriate Redfish
703 // enum
704 std::string rfBpLastState = "None";
705 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
706 "ProgressStages.Unspecified")
707 {
708 rfBpLastState = "None";
709 }
710 else if (dbusBootProgress ==
711 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
712 "PrimaryProcInit")
713 {
714 rfBpLastState = "PrimaryProcessorInitializationStarted";
715 }
716 else if (dbusBootProgress ==
717 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
718 "BusInit")
719 {
720 rfBpLastState = "BusInitializationStarted";
721 }
722 else if (dbusBootProgress ==
723 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
724 "MemoryInit")
725 {
726 rfBpLastState = "MemoryInitializationStarted";
727 }
728 else if (dbusBootProgress ==
729 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
730 "SecondaryProcInit")
731 {
732 rfBpLastState = "SecondaryProcessorInitializationStarted";
733 }
734 else if (dbusBootProgress ==
735 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
736 "PCIInit")
737 {
738 rfBpLastState = "PCIResourceConfigStarted";
739 }
740 else if (dbusBootProgress ==
741 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
742 "SystemSetup")
743 {
744 rfBpLastState = "SetupEntered";
745 }
746 else if (dbusBootProgress ==
747 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
748 "SystemInitComplete")
749 {
750 rfBpLastState = "SystemHardwareInitializationComplete";
751 }
752 else if (dbusBootProgress ==
753 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
754 "OSStart")
755 {
756 rfBpLastState = "OSBootStarted";
757 }
758 else if (dbusBootProgress ==
759 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
760 "OSRunning")
761 {
762 rfBpLastState = "OSRunning";
763 }
764 else
765 {
Ed Tanous62598e32023-07-17 17:06:25 -0700766 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600767 // Just return the default
768 }
769 return rfBpLastState;
770}
771
772/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500773 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 *
775 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 * @param[out] bootSource The DBus source
777 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400781inline int assignBootParameters(
782 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
783 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300785 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
786 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788 if (rfSource == "None")
789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700792 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530793 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
795 }
796 else if (rfSource == "Hdd")
797 {
798 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
799 }
800 else if (rfSource == "Diags")
801 {
802 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
803 }
804 else if (rfSource == "Cd")
805 {
806 bootSource =
807 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
808 }
809 else if (rfSource == "BiosSetup")
810 {
811 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530812 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 else if (rfSource == "Usb")
814 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700815 bootSource =
816 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700817 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818 else
819 {
Ed Tanous62598e32023-07-17 17:06:25 -0700820 BMCWEB_LOG_DEBUG(
821 "Invalid property value for BootSourceOverrideTarget: {}",
822 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700823 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700824 "BootSourceTargetOverride");
825 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530826 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700827 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828}
Ali Ahmed19817712021-06-29 17:01:52 -0500829
Andrew Geissler978b8802020-11-19 13:36:40 -0600830/**
831 * @brief Retrieves boot progress of the system
832 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700833 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200834 * @param[in] computerSystemIndex Index associated with the requested system
Andrew Geissler978b8802020-11-19 13:36:40 -0600835 *
836 * @return None.
837 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200838inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
839 const uint64_t computerSystemIndex)
Andrew Geissler978b8802020-11-19 13:36:40 -0600840{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800841 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200842 getHostStateServiceName(computerSystemIndex),
843 getHostStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700844 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700845 [asyncResp](const boost::system::error_code& ec,
846 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400847 if (ec)
848 {
849 // BootProgress is an optional object so just do nothing if
850 // not found
851 return;
852 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600853
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400854 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600855
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400856 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
857 dbusToRfBootProgress(bootProgressStr);
858 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600859}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530860
861/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000862 * @brief Retrieves boot progress Last Update of the system
863 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700864 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200865 * @param[in] computerSystemIndex Index associated with the requested system
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000866 *
867 * @return None.
868 */
869inline void getBootProgressLastStateTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200870 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
871 const uint64_t computerSystemIndex)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000872{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800873 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200874 getHostStateServiceName(computerSystemIndex),
875 getHostStateObjectPath(computerSystemIndex),
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000876 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700877 [asyncResp](const boost::system::error_code& ec,
878 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400879 if (ec)
880 {
881 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
882 return;
883 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000884
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400885 // BootProgressLastUpdate is the last time the BootProgress property
886 // was updated. The time is the Epoch time, number of microseconds
887 // since 1 Jan 1970 00::00::00 UTC."
888 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
889 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000890
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400891 // Convert to ISO 8601 standard
892 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
893 redfish::time_utils::getDateTimeUintUs(lastStateTime);
894 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000895}
896
897/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300898 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300899 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700900 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200901 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300902 *
903 * @return None.
904 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500905inline void getBootOverrideType(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200906 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
907 const uint64_t computerSystemIndex)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300908{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200909 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
910 std::to_string(computerSystemIndex));
911 path /= "boot";
912
Ed Tanousdeae6a72024-11-11 21:58:57 -0800913 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200914 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700915 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700916 [asyncResp](const boost::system::error_code& ec,
917 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400918 if (ec)
919 {
920 // not an error, don't have to have the interface
921 return;
922 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400924 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300925
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400926 asyncResp->res
927 .jsonValue["Boot"]
928 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
929 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300930
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400931 auto rfType = dbusToRfBootType(bootType);
932 if (rfType.empty())
933 {
934 messages::internalError(asyncResp->res);
935 return;
936 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300937
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400938 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
939 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300940}
941
942/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700945 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200946 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530947 *
948 * @return None.
949 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500950inline void getBootOverrideMode(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200951 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
952 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530953{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200954 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
955 std::to_string(computerSystemIndex));
956 path /= "boot";
Ed Tanousdeae6a72024-11-11 21:58:57 -0800957 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200958 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700959 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700960 [asyncResp](const boost::system::error_code& ec,
961 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400962 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530963 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400964 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
965 messages::internalError(asyncResp->res);
966 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400968
969 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
970
971 nlohmann::json::array_t allowed;
972 allowed.emplace_back("None");
973 allowed.emplace_back("Pxe");
974 allowed.emplace_back("Hdd");
975 allowed.emplace_back("Cd");
976 allowed.emplace_back("Diags");
977 allowed.emplace_back("BiosSetup");
978 allowed.emplace_back("Usb");
979
980 asyncResp->res
981 .jsonValue["Boot"]
982 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
983 std::move(allowed);
984 if (bootModeStr !=
985 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
986 {
987 auto rfMode = dbusToRfBootMode(bootModeStr);
988 if (!rfMode.empty())
989 {
990 asyncResp->res
991 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
992 }
993 }
994 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530995}
996
997/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300998 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530999 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001000 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001001 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301002 *
1003 * @return None.
1004 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001005inline void getBootOverrideSource(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001006 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1007 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001009 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1010 std::to_string(computerSystemIndex));
1011 path /= "boot";
1012
Ed Tanousdeae6a72024-11-11 21:58:57 -08001013 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001014 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001015 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001016 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1017 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001018 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001019 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001020 // Service not available, no error, just don't return
1021 // Boot Override Source information
1022 if (ec.value() != EBADR &&
1023 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001024 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001025 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1026 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001027 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001028 return;
1029 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301030
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001031 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301032
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001033 auto rfSource = dbusToRfBootSource(bootSourceStr);
1034 if (!rfSource.empty())
1035 {
1036 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1037 rfSource;
1038 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001039
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001040 // Get BootMode as BootSourceOverrideTarget is constructed
1041 // from both BootSource and BootMode
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001042 getBootOverrideMode(asyncResp, computerSystemIndex);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001043 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044}
1045
1046/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001047 * @brief This functions abstracts all the logic behind getting a
1048 * "BootSourceOverrideEnabled" property from an overall boot override enable
1049 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301050 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001051 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001052 * @param[in] computerSystemIndex Index associated with the requested system
1053 * @param[in] bootOverrideEnableSetting
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301054 *
1055 * @return None.
1056 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301057
Ed Tanousac106bf2023-06-07 09:24:59 -07001058inline void processBootOverrideEnable(
1059 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001060 const uint64_t computerSystemIndex, const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001061{
1062 if (!bootOverrideEnableSetting)
1063 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001064 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1065 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001066 return;
1067 }
1068
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001069 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1070 std::to_string(computerSystemIndex));
1071 path /= "boot";
1072 path /= "one_time";
1073
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074 // If boot source override is enabled, we need to check 'one_time'
1075 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001076 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001077 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001078 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001079 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001080 if (ec)
1081 {
1082 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1083 messages::internalError(asyncResp->res);
1084 return;
1085 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301086
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001087 if (oneTimeSetting)
1088 {
1089 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1090 "Once";
1091 }
1092 else
1093 {
1094 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1095 "Continuous";
1096 }
1097 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301098}
1099
1100/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001101 * @brief Retrieves boot override enable over DBUS
1102 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001103 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001104 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001105 *
1106 * @return None.
1107 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001108inline void getBootOverrideEnable(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001109 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1110 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001111{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001112 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1113 std::to_string(computerSystemIndex));
1114 path /= "boot";
1115
Ed Tanousdeae6a72024-11-11 21:58:57 -08001116 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001117 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001118 "xyz.openbmc_project.Object.Enable", "Enabled",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001119 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1120 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001121 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001122 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001123 // Service not available, no error, just don't return
1124 // Boot Override Enable information
1125 if (ec.value() != EBADR &&
1126 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001127 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001128 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1129 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001130 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001131 return;
1132 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001133
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001134 processBootOverrideEnable(asyncResp, computerSystemIndex,
1135 bootOverrideEnable);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001136 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001137}
1138
1139/**
1140 * @brief Retrieves boot source override properties
1141 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001142 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001143 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001144 *
1145 * @return None.
1146 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001147inline void getBootProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001148 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1149 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001150{
Ed Tanous62598e32023-07-17 17:06:25 -07001151 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001152
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001153 getBootOverrideSource(asyncResp, computerSystemIndex);
1154 getBootOverrideType(asyncResp, computerSystemIndex);
1155 getBootOverrideEnable(asyncResp, computerSystemIndex);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001156}
1157
1158/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001159 * @brief Retrieves the Last Reset Time
1160 *
1161 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1162 * and power off. Even though this is the "system" Redfish object look at the
1163 * chassis D-Bus interface for the LastStateChangeTime since this has the
1164 * last power operation time.
1165 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001166 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001167 *
1168 * @return None.
1169 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001170inline void getLastResetTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1172 const uint64_t computerSystemIndex)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001173{
Ed Tanous62598e32023-07-17 17:06:25 -07001174 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001175
Ed Tanousdeae6a72024-11-11 21:58:57 -08001176 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001177 getChassisStateServiceName(computerSystemIndex),
1178 getChassisStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001179 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001180 [asyncResp](const boost::system::error_code& ec,
1181 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001182 if (ec)
1183 {
1184 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1185 return;
1186 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001187
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001188 // LastStateChangeTime is epoch time, in milliseconds
1189 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1190 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001191
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001192 // Convert to ISO 8601 standard
1193 asyncResp->res.jsonValue["LastResetTime"] =
1194 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1195 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001196}
1197
1198/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001199 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1200 *
1201 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1202 * corresponding property "AttemptsLeft" that keeps track of the amount of
1203 * automatic retry attempts left are hosted in phosphor-state-manager through
1204 * dbus.
1205 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001206 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001207 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001208 *
1209 * @return None.
1210 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001211inline void getAutomaticRebootAttempts(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001212 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1213 const uint64_t computerSystemIndex)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001214{
Ed Tanous62598e32023-07-17 17:06:25 -07001215 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001216
Ed Tanousdeae6a72024-11-11 21:58:57 -08001217 dbus::utility::getAllProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001218 getHostStateServiceName(computerSystemIndex),
1219 getHostStateObjectPath(computerSystemIndex),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001220 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001221 [asyncResp{asyncResp}](
1222 const boost::system::error_code& ec,
1223 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001224 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001225 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301226 if (ec.value() != EBADR &&
1227 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001228 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301229 // Service not available, no error, just don't return
1230 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001231 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1232 messages::internalError(asyncResp->res);
1233 }
1234 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001235 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001236
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001237 const uint32_t* attemptsLeft = nullptr;
1238 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001239
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001240 const bool success = sdbusplus::unpackPropertiesNoThrow(
1241 dbus_utils::UnpackErrorPrinter(), propertiesList,
1242 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001243
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001244 if (!success)
1245 {
1246 messages::internalError(asyncResp->res);
1247 return;
1248 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001249
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001250 if (attemptsLeft != nullptr)
1251 {
1252 asyncResp->res
1253 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1254 *attemptsLeft;
1255 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001256
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001257 if (retryAttempts != nullptr)
1258 {
1259 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1260 *retryAttempts;
1261 }
1262 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001263}
1264
1265/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001266 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1267 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001268 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001269 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001270 *
1271 * @return None.
1272 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001273inline void getAutomaticRetryPolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001274 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1275 const uint64_t computerSystemIndex)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001276{
Ed Tanous62598e32023-07-17 17:06:25 -07001277 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001278
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001279 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1280 std::to_string(computerSystemIndex));
1281 path /= "auto_reboot";
1282
Ed Tanousdeae6a72024-11-11 21:58:57 -08001283 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001284 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001285 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001286 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1287 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001288 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001289 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301290 // Service not available, no error, just don't return
1291 // AutoReboot information
1292 if (ec.value() != EBADR &&
1293 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001294 {
1295 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1296 messages::internalError(asyncResp->res);
1297 }
1298 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001299 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001300
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001301 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1302 if (autoRebootEnabled)
1303 {
1304 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1305 "RetryAttempts";
1306 }
1307 else
1308 {
1309 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1310 "Disabled";
1311 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001312 getAutomaticRebootAttempts(asyncResp, computerSystemIndex);
Gunnar Mills69f35302020-05-17 16:06:31 -05001313
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001314 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1315 // and RetryAttempts. OpenBMC only supports Disabled and
1316 // RetryAttempts.
1317 nlohmann::json::array_t allowed;
1318 allowed.emplace_back("Disabled");
1319 allowed.emplace_back("RetryAttempts");
1320 asyncResp->res
1321 .jsonValue["Boot"]
1322 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1323 std::move(allowed);
1324 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001325}
1326
1327/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001328 * @brief Sets RetryAttempts
1329 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001330 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001331 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001332 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1333 *
1334 *@return None.
1335 */
1336
Ed Tanousac106bf2023-06-07 09:24:59 -07001337inline void setAutomaticRetryAttempts(
1338 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001339 const uint64_t computerSystemIndex, const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001340{
Ed Tanous62598e32023-07-17 17:06:25 -07001341 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001342
1343 setDbusProperty(asyncResp, "Boot/AutomaticRetryAttempts",
1344 getHostStateServiceName(computerSystemIndex),
1345 getHostStateObjectPath(computerSystemIndex),
1346 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1347 "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001348}
1349
Ed Tanous8d69c662023-06-21 10:29:06 -07001350inline computer_system::PowerRestorePolicyTypes
1351 redfishPowerRestorePolicyFromDbus(std::string_view value)
1352{
1353 if (value ==
1354 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1355 {
1356 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1357 }
1358 if (value ==
1359 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1360 {
1361 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1362 }
1363 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001364 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001365 {
1366 return computer_system::PowerRestorePolicyTypes::LastState;
1367 }
1368 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1369 {
1370 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1371 }
1372 return computer_system::PowerRestorePolicyTypes::Invalid;
1373}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001374/**
George Liuc6a620f2020-04-10 17:18:11 +08001375 * @brief Retrieves power restore policy over DBUS.
1376 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001377 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001378 *
1379 * @return None.
1380 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001381inline void getPowerRestorePolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001382 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1383 const uint64_t computerSystemIndex)
George Liuc6a620f2020-04-10 17:18:11 +08001384{
Ed Tanous62598e32023-07-17 17:06:25 -07001385 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001386
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001387 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1388 std::to_string(computerSystemIndex));
1389 path /= "power_restore_policy";
1390
Ed Tanousdeae6a72024-11-11 21:58:57 -08001391 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001392 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001393 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001394 [asyncResp](const boost::system::error_code& ec,
1395 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001396 if (ec)
1397 {
1398 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1399 return;
1400 }
1401 computer_system::PowerRestorePolicyTypes restore =
1402 redfishPowerRestorePolicyFromDbus(policy);
1403 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1404 {
1405 messages::internalError(asyncResp->res);
1406 return;
1407 }
George Liuc6a620f2020-04-10 17:18:11 +08001408
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001409 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1410 });
George Liuc6a620f2020-04-10 17:18:11 +08001411}
1412
1413/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001414 * @brief Stop Boot On Fault over DBUS.
1415 *
1416 * @param[in] asyncResp Shared pointer for generating response message.
1417 *
1418 * @return None.
1419 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001420inline void getStopBootOnFault(
1421 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001422{
Ed Tanous62598e32023-07-17 17:06:25 -07001423 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001424
Ed Tanousdeae6a72024-11-11 21:58:57 -08001425 dbus::utility::getProperty<bool>(
1426 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001427 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1428 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001429 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001430 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301431 // Service not available, no error, just don't return
1432 // StopBootOnFault information
1433 if (ec.value() != EBADR ||
1434 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001435 {
1436 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1437 messages::internalError(asyncResp->res);
1438 }
1439 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001440 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001441
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001442 if (value)
1443 {
1444 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1445 computer_system::StopBootOnFault::AnyFault;
1446 }
1447 else
1448 {
1449 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1450 computer_system::StopBootOnFault::Never;
1451 }
1452 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001453}
1454
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001455inline void getTrustedModuleRequiredToBootCallback(
1456 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1457 const uint64_t computerSystemIndex, const boost::system::error_code& ec,
1458 const dbus::utility::MapperGetSubTreeResponse& subtree)
1459{
1460 if (ec)
1461 {
1462 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}", ec);
1463 // This is an optional D-Bus object so just return if
1464 // error occurs
1465 return;
1466 }
1467 if (subtree.empty())
1468 {
1469 // As noted above, this is an optional interface so just return
1470 // if there is no instance found
1471 return;
1472 }
1473
1474 std::string path;
1475 std::string service;
1476
1477 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1478 {
1479 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1480 subtree, path, service))
1481 {
1482 return;
1483 }
1484 }
1485 else
1486 {
1487 // Make sure the Dbus response map has a service and objectPath
1488 // field
1489 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1490 {
1491 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1492 messages::internalError(asyncResp->res);
1493 return;
1494 }
1495
1496 path = subtree[0].first;
1497 service = subtree[0].second.begin()->first;
1498 }
1499
1500 BMCWEB_LOG_DEBUG("found tpm service {}", service);
1501 BMCWEB_LOG_DEBUG("found tpm path {}", path);
1502
1503 // Valid TPM Enable object found, now reading the current value
1504 dbus::utility::getProperty<bool>(
1505 service, path, "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1506 [asyncResp](const boost::system::error_code& ec2, bool tpmRequired) {
1507 if (ec2)
1508 {
1509 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
1510 ec2);
1511 messages::internalError(asyncResp->res);
1512 return;
1513 }
1514
1515 if (tpmRequired)
1516 {
1517 asyncResp->res
1518 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1519 "Required";
1520 }
1521 else
1522 {
1523 asyncResp->res
1524 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1525 "Disabled";
1526 }
1527 });
1528}
1529
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001530/**
Ali Ahmed19817712021-06-29 17:01:52 -05001531 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1532 * TPM is required for booting the host.
1533 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001534 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001535 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed19817712021-06-29 17:01:52 -05001536 *
1537 * @return None.
1538 */
1539inline void getTrustedModuleRequiredToBoot(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001540 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1541 const uint64_t computerSystemIndex)
Ali Ahmed19817712021-06-29 17:01:52 -05001542{
Ed Tanous62598e32023-07-17 17:06:25 -07001543 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001544 constexpr std::array<std::string_view, 1> interfaces = {
1545 "xyz.openbmc_project.Control.TPM.Policy"};
1546 dbus::utility::getSubTree(
1547 "/", 0, interfaces,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001548 std::bind_front(getTrustedModuleRequiredToBootCallback, asyncResp,
1549 computerSystemIndex));
Ali Ahmed19817712021-06-29 17:01:52 -05001550}
1551
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001552inline void setTrustedModuleRequiredToBootCallback(
1553 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1554 const uint64_t computerSystemIndex, const bool tpmRequired,
1555 const boost::system::error_code& ec,
1556 const dbus::utility::MapperGetSubTreeResponse& subtree)
1557{
1558 if (ec)
1559 {
1560 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}", ec);
1561 messages::internalError(asyncResp->res);
1562 return;
1563 }
1564 if (subtree.empty())
1565 {
1566 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
1567 "TrustedModuleRequiredToBoot");
1568 return;
1569 }
1570
1571 std::string path;
1572 std::string serv;
1573
1574 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1575 {
1576 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1577 subtree, path, serv))
1578 {
1579 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1580 messages::internalError(asyncResp->res);
1581 return;
1582 }
1583 }
1584 else
1585 {
1586 // Make sure the Dbus response map has a service and objectPath
1587 // field
1588 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1589 {
1590 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1591 messages::internalError(asyncResp->res);
1592 return;
1593 }
1594
1595 path = subtree[0].first;
1596 serv = subtree[0].second.begin()->first;
1597 }
1598
1599 if (serv.empty())
1600 {
1601 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1602 messages::internalError(asyncResp->res);
1603 return;
1604 }
1605
1606 // Valid TPM Enable object found, now setting the value
1607 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv, path,
1608 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1609 tpmRequired);
1610}
1611
Ali Ahmed19817712021-06-29 17:01:52 -05001612/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001613 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1614 * TPM is required for booting the host.
1615 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001616 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001617 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001618 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1619 *
1620 * @return None.
1621 */
1622inline void setTrustedModuleRequiredToBoot(
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001623 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1624 const uint64_t computerSystemIndex, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001625{
Ed Tanous62598e32023-07-17 17:06:25 -07001626 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001627 constexpr std::array<std::string_view, 1> interfaces = {
1628 "xyz.openbmc_project.Control.TPM.Policy"};
1629 dbus::utility::getSubTree(
1630 "/", 0, interfaces,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001631 std::bind_front(setTrustedModuleRequiredToBootCallback, asyncResp,
1632 computerSystemIndex, tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001633}
1634
1635/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301636 * @brief Sets boot properties into DBUS object(s).
1637 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001638 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001639 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001640 * @param[in] bootType The boot type to set.
1641 * @return Integer error code.
1642 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001643inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001644 const uint64_t computerSystemIndex,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001645 const std::optional<std::string>& bootType)
1646{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001647 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001648
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001649 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001650 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001651 return;
1652 }
1653
1654 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001655 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001656 // Figure out which DBUS interface and property to use
1657 if (*bootType == "Legacy")
1658 {
1659 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1660 }
1661 else if (*bootType == "UEFI")
1662 {
1663 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1664 }
1665 else
1666 {
Ed Tanous62598e32023-07-17 17:06:25 -07001667 BMCWEB_LOG_DEBUG("Invalid property value for "
1668 "BootSourceOverrideMode: {}",
1669 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001670 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001671 "BootSourceOverrideMode");
1672 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001673 }
1674
1675 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001676 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001677
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001678 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1679 std::to_string(computerSystemIndex));
1680 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301681 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001682 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001683 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301684 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001685}
1686
1687/**
1688 * @brief Sets boot properties into DBUS object(s).
1689 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001690 * @param[in] asyncResp Shared pointer for generating response
1691 * message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001692 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001693 * @param[in] bootType The boot type to set.
1694 * @return Integer error code.
1695 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001696inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001697 const uint64_t computerSystemIndex,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001698 const std::optional<std::string>& bootEnable)
1699{
1700 if (!bootEnable)
1701 {
1702 return;
1703 }
1704 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001705 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001706
1707 bool bootOverrideEnable = false;
1708 bool bootOverridePersistent = false;
1709 // Figure out which DBUS interface and property to use
1710 if (*bootEnable == "Disabled")
1711 {
1712 bootOverrideEnable = false;
1713 }
1714 else if (*bootEnable == "Once")
1715 {
1716 bootOverrideEnable = true;
1717 bootOverridePersistent = false;
1718 }
1719 else if (*bootEnable == "Continuous")
1720 {
1721 bootOverrideEnable = true;
1722 bootOverridePersistent = true;
1723 }
1724 else
1725 {
Ed Tanous62598e32023-07-17 17:06:25 -07001726 BMCWEB_LOG_DEBUG(
1727 "Invalid property value for BootSourceOverrideEnabled: {}",
1728 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001729 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001730 "BootSourceOverrideEnabled");
1731 return;
1732 }
1733
1734 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001735 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001736
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001737 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1738 std::to_string(computerSystemIndex));
1739 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301740 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001741 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001742 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301743 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001744
1745 if (!bootOverrideEnable)
1746 {
1747 return;
1748 }
1749
1750 // In case boot override is enabled we need to set correct value for the
1751 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001752 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1753 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001754
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001755 path /= "one_time";
Ginu Georgee93abac2024-06-14 17:35:27 +05301756 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001757 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001758 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301759 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001760}
1761
1762/**
1763 * @brief Sets boot properties into DBUS object(s).
1764 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001765 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001766 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301767 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301768 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001769 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301770 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001771inline void setBootModeOrSource(
1772 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001773 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001774 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301775{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001776 std::string bootSourceStr;
1777 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001778
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001779 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301780 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001781 return;
1782 }
1783
1784 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001785 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001786 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001787 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1788 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001789 {
Ed Tanous62598e32023-07-17 17:06:25 -07001790 BMCWEB_LOG_DEBUG(
1791 "Invalid property value for BootSourceOverrideTarget: {}",
1792 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001793 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001794 "BootSourceTargetOverride");
1795 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001796 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301797
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001798 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001799 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1800 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001801
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001802 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1803 std::to_string(computerSystemIndex));
1804 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301805 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001806 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001807 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301808 bootSourceStr);
1809 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001810 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001811 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301812 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001813}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001814
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001815/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001816 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301817 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001818 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001819 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301820 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001821 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301822 * @param[in] bootEnable The boot override enable from incoming RF request.
1823 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001824 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301825 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001826
Patrick Williams504af5a2025-02-03 14:29:03 -05001827inline void setBootProperties(
1828 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001829 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001830 const std::optional<std::string>& bootSource,
1831 const std::optional<std::string>& bootType,
1832 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301833{
Ed Tanous62598e32023-07-17 17:06:25 -07001834 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301835
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001836 setBootModeOrSource(asyncResp, computerSystemIndex, bootSource);
1837 setBootType(asyncResp, computerSystemIndex, bootType);
1838 setBootEnable(asyncResp, computerSystemIndex, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301839}
1840
George Liuc6a620f2020-04-10 17:18:11 +08001841/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001842 * @brief Sets AssetTag
1843 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001844 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001845 * @param[in] assetTag "AssetTag" from request.
1846 *
1847 * @return None.
1848 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001849inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001850 const std::string& assetTag)
1851{
George Liue99073f2022-12-09 11:06:16 +08001852 constexpr std::array<std::string_view, 1> interfaces = {
1853 "xyz.openbmc_project.Inventory.Item.System"};
1854 dbus::utility::getSubTree(
1855 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001856 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001857 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001858 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001859 if (ec)
1860 {
1861 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1862 messages::internalError(asyncResp->res);
1863 return;
1864 }
1865 if (subtree.empty())
1866 {
1867 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1868 messages::internalError(asyncResp->res);
1869 return;
1870 }
1871 // Assume only 1 system D-Bus object
1872 // Throw an error if there is more than 1
1873 if (subtree.size() > 1)
1874 {
1875 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1876 messages::internalError(asyncResp->res);
1877 return;
1878 }
1879 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1880 {
1881 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1882 messages::internalError(asyncResp->res);
1883 return;
1884 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001885
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001886 const std::string& path = subtree[0].first;
1887 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001888
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001889 if (service.empty())
1890 {
1891 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1892 messages::internalError(asyncResp->res);
1893 return;
1894 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001895
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001896 setDbusProperty(asyncResp, "AssetTag", service, path,
1897 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1898 "AssetTag", assetTag);
1899 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001900}
1901
1902/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001903 * @brief Validate the specified stopBootOnFault is valid and return the
1904 * stopBootOnFault name associated with that string
1905 *
1906 * @param[in] stopBootOnFaultString String representing the desired
1907 * stopBootOnFault
1908 *
1909 * @return stopBootOnFault value or empty if incoming value is not valid
1910 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001911inline std::optional<bool> validstopBootOnFault(
1912 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001913{
1914 if (stopBootOnFaultString == "AnyFault")
1915 {
1916 return true;
1917 }
1918
1919 if (stopBootOnFaultString == "Never")
1920 {
1921 return false;
1922 }
1923
1924 return std::nullopt;
1925}
1926
1927/**
1928 * @brief Sets stopBootOnFault
1929 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001930 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001931 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1932 *
1933 * @return None.
1934 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001935inline void setStopBootOnFault(
1936 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1937 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001938{
Ed Tanous62598e32023-07-17 17:06:25 -07001939 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001940
1941 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1942 if (!stopBootEnabled)
1943 {
Ed Tanous62598e32023-07-17 17:06:25 -07001944 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1945 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001946 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001947 "StopBootOnFault");
1948 return;
1949 }
1950
Ginu Georgee93abac2024-06-14 17:35:27 +05301951 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1952 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001953 sdbusplus::message::object_path(
1954 "/xyz/openbmc_project/logging/settings"),
1955 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301956 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001957}
1958
1959/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001960 * @brief Sets automaticRetry (Auto Reboot)
1961 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001962 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001963 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills69f35302020-05-17 16:06:31 -05001964 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1965 *
1966 * @return None.
1967 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001968inline void setAutomaticRetry(
1969 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001970 const uint64_t computerSystemIndex, const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001971{
Ed Tanous62598e32023-07-17 17:06:25 -07001972 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001973
1974 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001975 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001976
1977 if (automaticRetryConfig == "Disabled")
1978 {
1979 autoRebootEnabled = false;
1980 }
1981 else if (automaticRetryConfig == "RetryAttempts")
1982 {
1983 autoRebootEnabled = true;
1984 }
1985 else
1986 {
Ed Tanous62598e32023-07-17 17:06:25 -07001987 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1988 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001989 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001990 "AutomaticRetryConfig");
1991 return;
1992 }
1993
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001994 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1995 std::to_string(computerSystemIndex));
1996 path /= "auto_reboot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301997 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001998 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001999 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05302000 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05002001}
2002
Ed Tanous8d69c662023-06-21 10:29:06 -07002003inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
2004{
2005 if (policy == "AlwaysOn")
2006 {
2007 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
2008 }
2009 if (policy == "AlwaysOff")
2010 {
2011 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
2012 }
2013 if (policy == "LastState")
2014 {
2015 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
2016 }
2017 return "";
2018}
2019
Gunnar Mills69f35302020-05-17 16:06:31 -05002020/**
George Liuc6a620f2020-04-10 17:18:11 +08002021 * @brief Sets power restore policy properties.
2022 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002023 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02002024 * @param[in] computerSystemIndex Index associated with the requested system
George Liuc6a620f2020-04-10 17:18:11 +08002025 * @param[in] policy power restore policy properties from request.
2026 *
2027 * @return None.
2028 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002029inline void setPowerRestorePolicy(
2030 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02002031 const uint64_t computerSystemIndex, std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08002032{
Ed Tanous62598e32023-07-17 17:06:25 -07002033 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08002034
Ed Tanous8d69c662023-06-21 10:29:06 -07002035 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08002036
Ed Tanous8d69c662023-06-21 10:29:06 -07002037 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08002038 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002039 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06002040 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08002041 return;
2042 }
2043
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02002044 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
2045 std::to_string(computerSystemIndex));
2046 path /= "power_restore_policy";
2047 setDbusProperty(asyncResp, "PowerRestorePolicy",
2048 "xyz.openbmc_project.Settings", path,
2049 "xyz.openbmc_project.Control.Power.RestorePolicy",
2050 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08002051}
2052
AppaRao Pulia6349912019-10-18 17:16:08 +05302053/**
2054 * @brief Retrieves provisioning status
2055 *
Ed Tanous25b54db2024-04-17 15:40:31 -07002056 * @param[in] asyncResp Shared pointer for completing asynchronous
2057 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05302058 *
2059 * @return None.
2060 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002061inline void getProvisioningStatus(
2062 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05302063{
Ed Tanous62598e32023-07-17 17:06:25 -07002064 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002065 dbus::utility::getAllProperties(
2066 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2067 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07002068 [asyncResp](const boost::system::error_code& ec,
2069 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002070 nlohmann::json& oemPFR =
2071 asyncResp->res
2072 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
2073 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
2074 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
2075 oemPFR["@odata.type"] =
2076 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07002077
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002078 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05302079 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002080 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2081 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002082 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002083 FirmwareProvisioningStatus::NotProvisioned;
2084 return;
2085 }
2086
2087 const bool* provState = nullptr;
2088 const bool* lockState = nullptr;
2089
2090 const bool success = sdbusplus::unpackPropertiesNoThrow(
2091 dbus_utils::UnpackErrorPrinter(), propertiesList,
2092 "UfmProvisioned", provState, "UfmLocked", lockState);
2093
2094 if (!success)
2095 {
2096 messages::internalError(asyncResp->res);
2097 return;
2098 }
2099
2100 if ((provState == nullptr) || (lockState == nullptr))
2101 {
2102 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2103 messages::internalError(asyncResp->res);
2104 return;
2105 }
2106
2107 if (*provState)
2108 {
2109 if (*lockState)
2110 {
2111 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2112 FirmwareProvisioningStatus::ProvisionedAndLocked;
2113 }
2114 else
2115 {
2116 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2117 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2118 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302119 }
2120 else
2121 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002122 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002123 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302124 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002125 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302126}
AppaRao Pulia6349912019-10-18 17:16:08 +05302127
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302128/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002129 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002130 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002131 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002132 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002133 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002134 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002135inline computer_system::PowerMode translatePowerModeString(
2136 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002137{
Chris Cainb6655102024-02-01 14:35:33 -06002138 using PowerMode = computer_system::PowerMode;
2139
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002140 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002141 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002142 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002143 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002144 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002145 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002146 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002147 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002148 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002149 if (modeString ==
2150 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002151 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002152 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002153 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002154 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002155 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2156 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002157 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002158 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002159 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002160 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2161 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002162 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002163 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002164 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002165 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2166 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002167 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002168 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002169 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002170 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002171 return PowerMode::OEM;
2172 }
2173 // Any other values would be invalid
2174 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2175 return PowerMode::Invalid;
2176}
2177
Patrick Williams504af5a2025-02-03 14:29:03 -05002178inline void afterGetPowerMode(
2179 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2180 const boost::system::error_code& ec,
2181 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002182{
2183 if (ec)
2184 {
2185 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2186 messages::internalError(asyncResp->res);
2187 return;
2188 }
2189
2190 std::string powerMode;
2191 const std::vector<std::string>* allowedModes = nullptr;
2192 const bool success = sdbusplus::unpackPropertiesNoThrow(
2193 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2194 "AllowedPowerModes", allowedModes);
2195
2196 if (!success)
2197 {
2198 messages::internalError(asyncResp->res);
2199 return;
2200 }
2201
2202 nlohmann::json::array_t modeList;
2203 if (allowedModes == nullptr)
2204 {
2205 modeList.emplace_back("Static");
2206 modeList.emplace_back("MaximumPerformance");
2207 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002208 }
2209 else
2210 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002211 for (const auto& aMode : *allowedModes)
2212 {
2213 computer_system::PowerMode modeValue =
2214 translatePowerModeString(aMode);
2215 if (modeValue == computer_system::PowerMode::Invalid)
2216 {
2217 messages::internalError(asyncResp->res);
2218 continue;
2219 }
2220 modeList.emplace_back(modeValue);
2221 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002222 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002223 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002224
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002225 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2226 const computer_system::PowerMode modeValue =
2227 translatePowerModeString(powerMode);
2228 if (modeValue == computer_system::PowerMode::Invalid)
2229 {
2230 messages::internalError(asyncResp->res);
2231 return;
2232 }
2233 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2234}
Chris Cain3a2d04242021-05-28 16:57:10 -05002235/**
2236 * @brief Retrieves system power mode
2237 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002238 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002239 *
2240 * @return None.
2241 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002242inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002243{
Ed Tanous62598e32023-07-17 17:06:25 -07002244 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002245
2246 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002247 constexpr std::array<std::string_view, 1> interfaces = {
2248 "xyz.openbmc_project.Control.Power.Mode"};
2249 dbus::utility::getSubTree(
2250 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002251 [asyncResp](const boost::system::error_code& ec,
2252 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002253 if (ec)
2254 {
2255 BMCWEB_LOG_DEBUG(
2256 "DBUS response error on Power.Mode GetSubTree {}", ec);
2257 // This is an optional D-Bus object so just return if
2258 // error occurs
2259 return;
2260 }
2261 if (subtree.empty())
2262 {
2263 // As noted above, this is an optional interface so just return
2264 // if there is no instance found
2265 return;
2266 }
2267 if (subtree.size() > 1)
2268 {
2269 // More then one PowerMode object is not supported and is an
2270 // error
2271 BMCWEB_LOG_DEBUG(
2272 "Found more than 1 system D-Bus Power.Mode objects: {}",
2273 subtree.size());
2274 messages::internalError(asyncResp->res);
2275 return;
2276 }
2277 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2278 {
2279 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2280 messages::internalError(asyncResp->res);
2281 return;
2282 }
2283 const std::string& path = subtree[0].first;
2284 const std::string& service = subtree[0].second.begin()->first;
2285 if (service.empty())
2286 {
2287 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2288 messages::internalError(asyncResp->res);
2289 return;
2290 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002291
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002292 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002293 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002294 *crow::connections::systemBus, service, path,
2295 "xyz.openbmc_project.Control.Power.Mode",
2296 [asyncResp](
2297 const boost::system::error_code& ec2,
2298 const dbus::utility::DBusPropertiesMap& properties) {
2299 afterGetPowerMode(asyncResp, ec2, properties);
2300 });
George Liue99073f2022-12-09 11:06:16 +08002301 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002302}
2303
2304/**
2305 * @brief Validate the specified mode is valid and return the PowerMode
2306 * name associated with that string
2307 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002308 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002309 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002310 *
2311 * @return PowerMode value or empty string if mode is not valid
2312 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002313inline std::string validatePowerMode(
2314 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2315 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002316{
Chris Cainb6655102024-02-01 14:35:33 -06002317 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002318 std::string mode;
2319
Chris Cainb6655102024-02-01 14:35:33 -06002320 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002321 {
2322 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2323 }
Chris Cainb6655102024-02-01 14:35:33 -06002324 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002325 {
George Liu0fda0f12021-11-16 10:06:17 +08002326 mode =
2327 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002328 }
Chris Cainb6655102024-02-01 14:35:33 -06002329 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002330 {
2331 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2332 }
Chris Cainb6655102024-02-01 14:35:33 -06002333 else if (modeValue == PowerMode::BalancedPerformance)
2334 {
2335 mode =
2336 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2337 }
2338 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2339 {
2340 mode =
2341 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2342 }
2343 else if (modeValue == PowerMode::EfficiencyFavorPower)
2344 {
2345 mode =
2346 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2347 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002348 else
2349 {
Chris Cainb6655102024-02-01 14:35:33 -06002350 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002351 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002352 }
2353 return mode;
2354}
2355
2356/**
2357 * @brief Sets system power mode.
2358 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002359 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002360 * @param[in] pmode System power mode from request.
2361 *
2362 * @return None.
2363 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002364inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002365 const std::string& pmode)
2366{
Ed Tanous62598e32023-07-17 17:06:25 -07002367 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002368
Ed Tanousac106bf2023-06-07 09:24:59 -07002369 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002370 if (powerMode.empty())
2371 {
2372 return;
2373 }
2374
2375 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002376 constexpr std::array<std::string_view, 1> interfaces = {
2377 "xyz.openbmc_project.Control.Power.Mode"};
2378 dbus::utility::getSubTree(
2379 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002380 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002381 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002382 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002383 if (ec)
2384 {
2385 BMCWEB_LOG_ERROR(
2386 "DBUS response error on Power.Mode GetSubTree {}", ec);
2387 // This is an optional D-Bus object, but user attempted to patch
2388 messages::internalError(asyncResp->res);
2389 return;
2390 }
2391 if (subtree.empty())
2392 {
2393 // This is an optional D-Bus object, but user attempted to patch
2394 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2395 "PowerMode");
2396 return;
2397 }
2398 if (subtree.size() > 1)
2399 {
2400 // More then one PowerMode object is not supported and is an
2401 // error
2402 BMCWEB_LOG_DEBUG(
2403 "Found more than 1 system D-Bus Power.Mode objects: {}",
2404 subtree.size());
2405 messages::internalError(asyncResp->res);
2406 return;
2407 }
2408 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2409 {
2410 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2411 messages::internalError(asyncResp->res);
2412 return;
2413 }
2414 const std::string& path = subtree[0].first;
2415 const std::string& service = subtree[0].second.begin()->first;
2416 if (service.empty())
2417 {
2418 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2419 messages::internalError(asyncResp->res);
2420 return;
2421 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002422
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002423 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002424
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002425 // Set the Power Mode property
2426 setDbusProperty(asyncResp, "PowerMode", service, path,
2427 "xyz.openbmc_project.Control.Power.Mode",
2428 "PowerMode", powerMode);
2429 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002430}
2431
2432/**
Yong Li51709ff2019-09-30 14:13:04 +08002433 * @brief Translates watchdog timeout action DBUS property value to redfish.
2434 *
2435 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2436 *
2437 * @return Returns as a string, the timeout action in Redfish terms. If
2438 * translation cannot be done, returns an empty string.
2439 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002440inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002441{
2442 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2443 {
2444 return "None";
2445 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002446 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002447 {
2448 return "ResetSystem";
2449 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002450 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002451 {
2452 return "PowerDown";
2453 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002454 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002455 {
2456 return "PowerCycle";
2457 }
2458
2459 return "";
2460}
2461
2462/**
Yong Lic45f0082019-10-10 14:19:01 +08002463 *@brief Translates timeout action from Redfish to DBUS property value.
2464 *
2465 *@param[in] rfAction The timeout action in Redfish.
2466 *
2467 *@return Returns as a string, the time_out action as expected by DBUS.
2468 *If translation cannot be done, returns an empty string.
2469 */
2470
Ed Tanous23a21a12020-07-25 04:45:05 +00002471inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002472{
2473 if (rfAction == "None")
2474 {
2475 return "xyz.openbmc_project.State.Watchdog.Action.None";
2476 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002477 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002478 {
2479 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2480 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002481 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002482 {
2483 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2484 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002485 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002486 {
2487 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2488 }
2489
2490 return "";
2491}
2492
2493/**
Yong Li51709ff2019-09-30 14:13:04 +08002494 * @brief Retrieves host watchdog timer properties over DBUS
2495 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002496 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002497 *
2498 * @return None.
2499 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002500inline void getHostWatchdogTimer(
2501 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002502{
Ed Tanous62598e32023-07-17 17:06:25 -07002503 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002504 dbus::utility::getAllProperties(
2505 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002506 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002507 [asyncResp](const boost::system::error_code& ec,
2508 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002509 if (ec)
2510 {
2511 // watchdog service is stopped
2512 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2513 return;
2514 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002515
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002516 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002517
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002518 nlohmann::json& hostWatchdogTimer =
2519 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002520
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002521 // watchdog service is running/enabled
2522 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002523
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002524 const bool* enabled = nullptr;
2525 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002526
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002527 const bool success = sdbusplus::unpackPropertiesNoThrow(
2528 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2529 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002530
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002531 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002532 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002533 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002534 return;
2535 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002536
2537 if (enabled != nullptr)
2538 {
2539 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2540 }
2541
2542 if (expireAction != nullptr)
2543 {
2544 std::string action = dbusToRfWatchdogAction(*expireAction);
2545 if (action.empty())
2546 {
2547 messages::internalError(asyncResp->res);
2548 return;
2549 }
2550 hostWatchdogTimer["TimeoutAction"] = action;
2551 }
2552 });
Yong Li51709ff2019-09-30 14:13:04 +08002553}
2554
2555/**
Yong Lic45f0082019-10-10 14:19:01 +08002556 * @brief Sets Host WatchDog Timer properties.
2557 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002558 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002559 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2560 * RF request.
2561 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2562 *
2563 * @return None.
2564 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002565inline void setWDTProperties(
2566 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2567 const std::optional<bool> wdtEnable,
2568 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002569{
Ed Tanous62598e32023-07-17 17:06:25 -07002570 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002571
2572 if (wdtTimeOutAction)
2573 {
2574 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2575 // check if TimeOut Action is Valid
2576 if (wdtTimeOutActStr.empty())
2577 {
Ed Tanous62598e32023-07-17 17:06:25 -07002578 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2579 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002580 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002581 "TimeoutAction");
2582 return;
2583 }
2584
Ginu Georgee93abac2024-06-14 17:35:27 +05302585 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2586 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002587 sdbusplus::message::object_path(
2588 "/xyz/openbmc_project/watchdog/host0"),
2589 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302590 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002591 }
2592
2593 if (wdtEnable)
2594 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302595 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2596 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002597 sdbusplus::message::object_path(
2598 "/xyz/openbmc_project/watchdog/host0"),
2599 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302600 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002601 }
2602}
2603
Chris Cain37bbf982021-09-20 10:53:09 -05002604/**
2605 * @brief Parse the Idle Power Saver properties into json
2606 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002607 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002608 * @param[in] properties IPS property data from DBus.
2609 *
2610 * @return true if successful
2611 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002612inline bool parseIpsProperties(
2613 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2614 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002615{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002616 const bool* enabled = nullptr;
2617 const uint8_t* enterUtilizationPercent = nullptr;
2618 const uint64_t* enterDwellTime = nullptr;
2619 const uint8_t* exitUtilizationPercent = nullptr;
2620 const uint64_t* exitDwellTime = nullptr;
2621
2622 const bool success = sdbusplus::unpackPropertiesNoThrow(
2623 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002624 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2625 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2626 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002627
2628 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002629 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002630 return false;
2631 }
2632
2633 if (enabled != nullptr)
2634 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002635 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002636 }
2637
2638 if (enterUtilizationPercent != nullptr)
2639 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002640 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002641 *enterUtilizationPercent;
2642 }
2643
2644 if (enterDwellTime != nullptr)
2645 {
2646 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002647 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002648 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2649 .count();
2650 }
2651
2652 if (exitUtilizationPercent != nullptr)
2653 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002654 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002655 *exitUtilizationPercent;
2656 }
2657
2658 if (exitDwellTime != nullptr)
2659 {
2660 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002661 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002662 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2663 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002664 }
2665
2666 return true;
2667}
2668
2669/**
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002670 * @brief Retrieves idle power saver properties over DBUS
Chris Cain37bbf982021-09-20 10:53:09 -05002671 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002672 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002673 *
2674 * @return None.
2675 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002676inline void getIdlePowerSaver(
2677 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002678{
Ed Tanous62598e32023-07-17 17:06:25 -07002679 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002680
2681 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002682 constexpr std::array<std::string_view, 1> interfaces = {
2683 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2684 dbus::utility::getSubTree(
2685 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002686 [asyncResp](const boost::system::error_code& ec,
2687 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002688 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002689 {
Ed Tanous62598e32023-07-17 17:06:25 -07002690 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002691 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2692 ec);
2693 messages::internalError(asyncResp->res);
2694 return;
2695 }
2696 if (subtree.empty())
2697 {
2698 // This is an optional interface so just return
2699 // if there is no instance found
2700 BMCWEB_LOG_DEBUG("No instances found");
2701 return;
2702 }
2703 if (subtree.size() > 1)
2704 {
2705 // More then one PowerIdlePowerSaver object is not supported and
2706 // is an error
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002707 BMCWEB_LOG_DEBUG(
2708 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2709 subtree.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002710 messages::internalError(asyncResp->res);
2711 return;
2712 }
2713 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2714 {
2715 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2716 messages::internalError(asyncResp->res);
2717 return;
2718 }
2719 const std::string& path = subtree[0].first;
2720 const std::string& service = subtree[0].second.begin()->first;
2721 if (service.empty())
2722 {
2723 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002724 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002725 return;
2726 }
2727
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002728 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002729 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002730 *crow::connections::systemBus, service, path,
2731 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2732 [asyncResp](
2733 const boost::system::error_code& ec2,
2734 const dbus::utility::DBusPropertiesMap& properties) {
2735 if (ec2)
2736 {
2737 BMCWEB_LOG_ERROR(
2738 "DBUS response error on IdlePowerSaver GetAll: {}",
2739 ec2);
2740 messages::internalError(asyncResp->res);
2741 return;
2742 }
2743
2744 if (!parseIpsProperties(asyncResp, properties))
2745 {
2746 messages::internalError(asyncResp->res);
2747 return;
2748 }
2749 });
George Liue99073f2022-12-09 11:06:16 +08002750 });
Chris Cain37bbf982021-09-20 10:53:09 -05002751
Ed Tanous62598e32023-07-17 17:06:25 -07002752 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002753}
2754
2755/**
2756 * @brief Sets Idle Power Saver properties.
2757 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002758 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002759 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2760 * RF request.
2761 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2762 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2763 * before entering idle state.
2764 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2765 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2766 * before exiting idle state
2767 *
2768 * @return None.
2769 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002770inline void setIdlePowerSaver(
2771 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2772 const std::optional<bool> ipsEnable,
2773 const std::optional<uint8_t> ipsEnterUtil,
2774 const std::optional<uint64_t> ipsEnterTime,
2775 const std::optional<uint8_t> ipsExitUtil,
2776 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002777{
Ed Tanous62598e32023-07-17 17:06:25 -07002778 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002779
2780 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002781 constexpr std::array<std::string_view, 1> interfaces = {
2782 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2783 dbus::utility::getSubTree(
2784 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002785 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002786 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002787 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002788 if (ec)
2789 {
2790 BMCWEB_LOG_ERROR(
2791 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2792 ec);
2793 messages::internalError(asyncResp->res);
2794 return;
2795 }
2796 if (subtree.empty())
2797 {
2798 // This is an optional D-Bus object, but user attempted to patch
2799 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2800 "IdlePowerSaver");
2801 return;
2802 }
2803 if (subtree.size() > 1)
2804 {
2805 // More then one PowerIdlePowerSaver object is not supported and
2806 // is an error
2807 BMCWEB_LOG_DEBUG(
2808 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2809 subtree.size());
2810 messages::internalError(asyncResp->res);
2811 return;
2812 }
2813 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2814 {
2815 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2816 messages::internalError(asyncResp->res);
2817 return;
2818 }
2819 const std::string& path = subtree[0].first;
2820 const std::string& service = subtree[0].second.begin()->first;
2821 if (service.empty())
2822 {
2823 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2824 messages::internalError(asyncResp->res);
2825 return;
2826 }
Chris Cain37bbf982021-09-20 10:53:09 -05002827
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002828 // Valid Power IdlePowerSaver object found, now set any values that
2829 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002830
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002831 if (ipsEnable)
2832 {
2833 setDbusProperty(
2834 asyncResp, "IdlePowerSaver/Enabled", service, path,
2835 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2836 "Enabled", *ipsEnable);
2837 }
2838 if (ipsEnterUtil)
2839 {
2840 setDbusProperty(
2841 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2842 service, path,
2843 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2844 "EnterUtilizationPercent", *ipsEnterUtil);
2845 }
2846 if (ipsEnterTime)
2847 {
2848 // Convert from seconds into milliseconds for DBus
2849 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2850 setDbusProperty(
2851 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2852 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2853 "EnterDwellTime", timeMilliseconds);
2854 }
2855 if (ipsExitUtil)
2856 {
2857 setDbusProperty(
2858 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2859 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2860 "ExitUtilizationPercent", *ipsExitUtil);
2861 }
2862 if (ipsExitTime)
2863 {
2864 // Convert from seconds into milliseconds for DBus
2865 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2866 setDbusProperty(
2867 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2868 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2869 "ExitDwellTime", timeMilliseconds);
2870 }
2871 });
Chris Cain37bbf982021-09-20 10:53:09 -05002872
Ed Tanous62598e32023-07-17 17:06:25 -07002873 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002874}
2875
Ed Tanousc1e219d2023-06-07 10:34:33 -07002876inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002877 crow::App& app, const crow::Request& req,
2878 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2879{
2880 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2881 {
2882 return;
2883 }
2884 asyncResp->res.addHeader(
2885 boost::beast::http::field::link,
2886 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2887}
2888
Ed Tanousc1e219d2023-06-07 10:34:33 -07002889inline void handleComputerSystemCollectionGet(
2890 crow::App& app, const crow::Request& req,
2891 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2892{
2893 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2894 {
2895 return;
2896 }
2897
2898 asyncResp->res.addHeader(
2899 boost::beast::http::field::link,
2900 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2901 asyncResp->res.jsonValue["@odata.type"] =
2902 "#ComputerSystemCollection.ComputerSystemCollection";
2903 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2904 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2905
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002906 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002907}
2908
Yong Lic45f0082019-10-10 14:19:01 +08002909/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002910 * Function transceives data with dbus directly.
2911 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002912inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002913{
Patrick Williams89492a12023-05-10 07:51:34 -05002914 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2915 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2916 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002917 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002918 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002919
Ed Tanous177612a2025-02-14 15:16:09 -08002920 dbus::utility::async_method_call(
2921 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002922 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002923 if (ec)
2924 {
2925 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2926 messages::internalError(asyncResp->res);
2927 return;
2928 }
2929 messages::success(asyncResp->res);
2930 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002931 serviceName, objectPath, interfaceName, method);
2932}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002933
Ed Tanousc1e219d2023-06-07 10:34:33 -07002934inline void handleComputerSystemResetActionPost(
2935 crow::App& app, const crow::Request& req,
2936 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2937 const std::string& systemName)
2938{
2939 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2940 {
2941 return;
2942 }
Gunnar Millsdd7090e2024-07-30 15:23:05 -05002943
2944 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2945 {
2946 if (systemName == "hypervisor")
2947 {
2948 handleHypervisorSystemResetPost(req, asyncResp);
2949 return;
2950 }
2951 }
2952
Ed Tanous253f11b2024-05-16 09:38:31 -07002953 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002954 {
2955 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2956 systemName);
2957 return;
2958 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002959 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002960 {
2961 // Option currently returns no systems. TBD
2962 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2963 systemName);
2964 return;
2965 }
2966 std::string resetType;
2967 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2968 {
2969 return;
2970 }
2971
2972 // Get the command and host vs. chassis
2973 std::string command;
2974 bool hostCommand = true;
2975 if ((resetType == "On") || (resetType == "ForceOn"))
2976 {
2977 command = "xyz.openbmc_project.State.Host.Transition.On";
2978 hostCommand = true;
2979 }
2980 else if (resetType == "ForceOff")
2981 {
2982 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2983 hostCommand = false;
2984 }
2985 else if (resetType == "ForceRestart")
2986 {
2987 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2988 hostCommand = true;
2989 }
2990 else if (resetType == "GracefulShutdown")
2991 {
2992 command = "xyz.openbmc_project.State.Host.Transition.Off";
2993 hostCommand = true;
2994 }
2995 else if (resetType == "GracefulRestart")
2996 {
2997 command =
2998 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2999 hostCommand = true;
3000 }
3001 else if (resetType == "PowerCycle")
3002 {
3003 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
3004 hostCommand = true;
3005 }
3006 else if (resetType == "Nmi")
3007 {
3008 doNMI(asyncResp);
3009 return;
3010 }
3011 else
3012 {
3013 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
3014 return;
3015 }
Ed Tanousd02aad32024-02-13 14:43:34 -08003016 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07003017
3018 if (hostCommand)
3019 {
Ginu Georgee93abac2024-06-14 17:35:27 +05303020 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08003021 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05303022 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003023 }
3024 else
3025 {
Ginu Georgee93abac2024-06-14 17:35:27 +05303026 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08003027 statePath / "chassis0",
3028 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05303029 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003030 }
3031}
3032
Ed Tanousc1e219d2023-06-07 10:34:33 -07003033inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003034 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003035 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3036 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003037{
3038 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3039 {
3040 return;
3041 }
3042
3043 asyncResp->res.addHeader(
3044 boost::beast::http::field::link,
3045 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3046}
3047
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003048inline void afterPortRequest(
3049 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3050 const boost::system::error_code& ec,
3051 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3052{
3053 if (ec)
3054 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003055 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003056 messages::internalError(asyncResp->res);
3057 return;
3058 }
3059 for (const auto& data : socketData)
3060 {
3061 const std::string& socketPath = get<0>(data);
3062 const std::string& protocolName = get<1>(data);
3063 bool isProtocolEnabled = get<2>(data);
3064 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3065 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3066 // need to retrieve port number for
3067 // obmc-console-ssh service
3068 if (protocolName == "SSH")
3069 {
3070 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003071 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003072 int portNumber) {
3073 if (ec1)
3074 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003075 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003076 messages::internalError(asyncResp->res);
3077 return;
3078 }
3079 nlohmann::json& dataJson1 =
3080 asyncResp->res.jsonValue["SerialConsole"];
3081 dataJson1[protocolName]["Port"] = portNumber;
3082 });
3083 }
3084 }
3085}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003086
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003087/**
3088 * @brief process the GET request after getting the computerSystemIndex
3089 *
3090 * @param[in] asyncResp Shared pointer for completing asynchronous
3091 * calls
3092 * @param[in] systemName Name of the requested system
3093 * @param[in] computerSystemIndex Index associated with the requested system
3094 *
3095 * @return None
3096 */
3097inline void processComputerSystemGet(
Patrick Williams504af5a2025-02-03 14:29:03 -05003098 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003099 const std::string& systemName, const uint64_t computerSystemIndex)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003100{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003101 asyncResp->res.addHeader(
3102 boost::beast::http::field::link,
3103 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3104 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003105 "#ComputerSystem.v1_22_0.ComputerSystem";
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003106 asyncResp->res.jsonValue["Name"] = systemName;
3107 asyncResp->res.jsonValue["Id"] = systemName;
Ed Tanous539d8c62024-06-19 14:38:27 -07003108 asyncResp->res.jsonValue["SystemType"] =
3109 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003110 asyncResp->res.jsonValue["Description"] = "Computer System";
3111 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003112 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003113 double(0);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003114 asyncResp->res.jsonValue["@odata.id"] =
3115 boost::urls::format("/redfish/v1/Systems/{}", systemName);
Ed Tanous04a258f2018-10-15 08:00:41 -07003116
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003117 // Currently not supported on multi-host. TBD
3118 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3119 {
3120 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3121 boost::urls::format("/redfish/v1/Systems/{}/Bios", systemName);
3122 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3123 boost::urls::format("/redfish/v1/Systems/{}/Processors",
3124 systemName);
3125 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3126 boost::urls::format("/redfish/v1/Systems/{}/Memory", systemName);
3127 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3128 boost::urls::format("/redfish/v1/Systems/{}/Storage", systemName);
3129 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3130 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3131 systemName);
3132 }
Ed Tanous029573d2019-02-01 10:57:49 -08003133
Ed Tanousc1e219d2023-06-07 10:34:33 -07003134 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003135 boost::urls::format(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003136 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003137 asyncResp->res
3138 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003139 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003140 systemName);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003141
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003142 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3143 boost::urls::format("/redfish/v1/Systems/{}/LogServices", systemName);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003144
Ed Tanousc1e219d2023-06-07 10:34:33 -07003145 nlohmann::json::array_t managedBy;
3146 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003147 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3148 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003149 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003150 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3151 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003152
Ed Tanousc1e219d2023-06-07 10:34:33 -07003153 // Fill in SerialConsole info
3154 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3155 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003156
Ed Tanousc1e219d2023-06-07 10:34:33 -07003157 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3158 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3159 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3160 "Press ~. to exit console";
3161 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3162 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003163
Ed Tanous25b54db2024-04-17 15:40:31 -07003164 if constexpr (BMCWEB_KVM)
3165 {
3166 // Fill in GraphicalConsole info
3167 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3168 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3169 4;
3170 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3171 nlohmann::json::array_t({"KVMIP"});
3172 }
James Feistb49ac872019-05-21 15:12:01 -07003173
Janet Adkins2eaa9272025-04-17 10:30:43 -05003174 systems_utils::getValidSystemsPath(
3175 asyncResp, systemName,
3176 [asyncResp,
3177 systemName](const std::optional<std::string>& validSystemsPath) {
3178 if (validSystemsPath)
3179 {
3180 getLocationIndicatorActive(asyncResp, *validSystemsPath);
3181 }
3182 });
3183
Janet Adkinsf664fd82025-07-23 14:01:43 -05003184 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3185 {
3186 getIndicatorLedState(asyncResp);
3187 }
3188
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003189 // Currently not supported on multi-host.
3190 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3191 {
3192 getComputerSystem(asyncResp);
3193 // Todo: chassis matching could be handled by patch
3194 // https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60793
3195 getMainChassisId(
3196 asyncResp, [](const std::string& chassisId,
3197 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3198 nlohmann::json::array_t chassisArray;
3199 nlohmann::json& chassis = chassisArray.emplace_back();
3200 chassis["@odata.id"] =
3201 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3202 aRsp->res.jsonValue["Links"]["Chassis"] =
3203 std::move(chassisArray);
3204 });
3205
3206 pcie_util::getPCIeDeviceList(
3207 asyncResp, nlohmann::json::json_pointer("/PCIeDevices"));
3208 }
3209 getHostState(asyncResp, computerSystemIndex);
3210 getBootProperties(asyncResp, computerSystemIndex);
3211 getBootProgress(asyncResp, computerSystemIndex);
3212 getBootProgressLastStateTime(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003213 getHostWatchdogTimer(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003214 getPowerRestorePolicy(asyncResp, computerSystemIndex);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003215 getStopBootOnFault(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003216 getAutomaticRetryPolicy(asyncResp, computerSystemIndex);
3217 getLastResetTime(asyncResp, computerSystemIndex);
Ed Tanous25b54db2024-04-17 15:40:31 -07003218 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3219 {
3220 getProvisioningStatus(asyncResp);
3221 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003222 getTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003223 getPowerMode(asyncResp);
3224 getIdlePowerSaver(asyncResp);
3225}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003226
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003227inline void handleComputerSystemGet(
3228 crow::App& app, const crow::Request& req,
3229 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3230 const std::string& systemName)
3231{
3232 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3233 {
3234 return;
3235 }
3236
3237 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
3238 {
3239 if (systemName == "hypervisor")
3240 {
3241 handleHypervisorSystemGet(asyncResp);
3242 return;
3243 }
3244 }
3245
3246 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3247 {
3248 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3249 {
3250 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3251 systemName);
3252 return;
3253 }
3254 }
3255
3256 BMCWEB_LOG_DEBUG("requested system = {}", systemName);
3257 getComputerSystemIndex(
3258 asyncResp, systemName,
3259 std::bind_front(processComputerSystemGet, asyncResp, systemName));
3260}
3261
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003262struct PatchParams
Ed Tanousc1e219d2023-06-07 10:34:33 -07003263{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003264 std::optional<bool> locationIndicatorActive;
3265 std::optional<std::string> indicatorLed;
3266 std::optional<std::string> assetTag;
3267 std::optional<std::string> powerRestorePolicy;
3268 std::optional<std::string> powerMode;
3269 std::optional<bool> wdtEnable;
3270 std::optional<std::string> wdtTimeOutAction;
3271 std::optional<std::string> bootSource;
3272 std::optional<std::string> bootType;
3273 std::optional<std::string> bootEnable;
3274 std::optional<std::string> bootAutomaticRetry;
3275 std::optional<uint32_t> bootAutomaticRetryAttempts;
3276 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003277 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003278 std::optional<bool> ipsEnable;
3279 std::optional<uint8_t> ipsEnterUtil;
3280 std::optional<uint64_t> ipsEnterTime;
3281 std::optional<uint8_t> ipsExitUtil;
3282 std::optional<uint64_t> ipsExitTime;
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003283};
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003284
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003285/**
3286 * @brief process the POST request after getting the computerSystemIndex
3287 *
3288 * @param[in] asyncResp Shared pointer for completing asynchronous
3289 * calls
3290 * @param[in] patchParams Struct containing the property we want to
3291 * patch
3292 * @param[in] computerSystemIndex Index associated with the requested system
3293 *
3294 * @return None
3295 */
James Feistb49ac872019-05-21 15:12:01 -07003296
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003297inline void processComputerSystemPatch(
3298 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3299 std::string& systemName, PatchParams& patchParams,
3300 const uint64_t computerSystemIndex)
3301{
Janet Adkinsf664fd82025-07-23 14:01:43 -05003302 if constexpr (!BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3303 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003304 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003305 {
3306 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
3307 return;
3308 }
3309 }
3310
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003311 if (patchParams.assetTag)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003312 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003313 setAssetTag(asyncResp, *patchParams.assetTag);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003314 }
James Feistb49ac872019-05-21 15:12:01 -07003315
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003316 if (patchParams.wdtEnable || patchParams.wdtTimeOutAction)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003317 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003318 setWDTProperties(asyncResp, patchParams.wdtEnable,
3319 patchParams.wdtTimeOutAction);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003320 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003321
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003322 if (patchParams.bootSource || patchParams.bootType ||
3323 patchParams.bootEnable)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003324 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003325 setBootProperties(asyncResp, computerSystemIndex,
3326 patchParams.bootSource, patchParams.bootType,
3327 patchParams.bootEnable);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003328 }
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003329 if (patchParams.bootAutomaticRetry)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003330 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003331 setAutomaticRetry(asyncResp, computerSystemIndex,
3332 *patchParams.bootAutomaticRetry);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003333 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003334
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003335 if (patchParams.bootAutomaticRetryAttempts)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003336 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003337 setAutomaticRetryAttempts(
3338 asyncResp, computerSystemIndex,
3339 patchParams.bootAutomaticRetryAttempts.value());
Ed Tanousc1e219d2023-06-07 10:34:33 -07003340 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003341
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003342 if (patchParams.bootTrustedModuleRequired)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003343 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003344 setTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex,
3345 *patchParams.bootTrustedModuleRequired);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003346 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003347
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003348 if (patchParams.stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003349 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003350 setStopBootOnFault(asyncResp, *patchParams.stopBootOnFault);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003351 }
3352
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003353 if (patchParams.locationIndicatorActive)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003354 {
Janet Adkins2eaa9272025-04-17 10:30:43 -05003355 systems_utils::getValidSystemsPath(
3356 asyncResp, systemName,
3357 [asyncResp, systemName,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003358 locationIndicatorActive{*patchParams.locationIndicatorActive}](
Janet Adkins2eaa9272025-04-17 10:30:43 -05003359 const std::optional<std::string>& validSystemsPath) {
3360 if (!validSystemsPath)
3361 {
3362 messages::resourceNotFound(asyncResp->res, "Systems",
3363 systemName);
3364 return;
3365 }
3366 setLocationIndicatorActive(asyncResp, *validSystemsPath,
3367 locationIndicatorActive);
3368 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003369 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003370
Janet Adkinsf664fd82025-07-23 14:01:43 -05003371 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003372 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003373 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003374 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003375 setIndicatorLedState(asyncResp, *patchParams.indicatorLed);
Janet Adkinsf664fd82025-07-23 14:01:43 -05003376 asyncResp->res.addHeader(boost::beast::http::field::warning,
3377 "299 - \"IndicatorLED is deprecated. Use "
3378 "LocationIndicatorActive instead.\"");
3379 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003380 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003381
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003382 if (patchParams.powerRestorePolicy)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003383 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003384 setPowerRestorePolicy(asyncResp, computerSystemIndex,
3385 *patchParams.powerRestorePolicy);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003386 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003387
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003388 if (patchParams.powerMode)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003389 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003390 setPowerMode(asyncResp, *patchParams.powerMode);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003391 }
Chris Cain37bbf982021-09-20 10:53:09 -05003392
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003393 if (patchParams.ipsEnable || patchParams.ipsEnterUtil ||
3394 patchParams.ipsEnterTime || patchParams.ipsExitUtil ||
3395 patchParams.ipsExitTime)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003396 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003397 setIdlePowerSaver(asyncResp, patchParams.ipsEnable,
3398 patchParams.ipsEnterUtil, patchParams.ipsEnterTime,
3399 patchParams.ipsExitUtil, patchParams.ipsExitTime);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003400 }
3401}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303402
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003403inline void handleComputerSystemPatch(
3404 crow::App& app, const crow::Request& req,
3405 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3406 const std::string& systemName)
3407{
3408 PatchParams patchParams;
3409
3410 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3411 {
3412 return;
3413 }
3414
3415 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3416 {
3417 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3418 {
3419 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3420 systemName);
3421 return;
3422 }
3423 }
3424
3425 asyncResp->res.addHeader(
3426 boost::beast::http::field::link,
3427 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3428
3429 if (!json_util::readJsonPatch(
3430 req, asyncResp->res, //
3431 "AssetTag", patchParams.assetTag, //
3432 "Boot/AutomaticRetryAttempts",
3433 patchParams.bootAutomaticRetryAttempts, //
3434 "Boot/AutomaticRetryConfig", patchParams.bootAutomaticRetry, //
3435 "Boot/BootSourceOverrideEnabled", patchParams.bootEnable, //
3436 "Boot/BootSourceOverrideMode", patchParams.bootType, //
3437 "Boot/BootSourceOverrideTarget", patchParams.bootSource, //
3438 "Boot/StopBootOnFault", patchParams.stopBootOnFault, //
3439 "Boot/TrustedModuleRequiredToBoot",
3440 patchParams.bootTrustedModuleRequired, //
3441 "HostWatchdogTimer/FunctionEnabled", patchParams.wdtEnable, //
3442 "HostWatchdogTimer/TimeoutAction", patchParams.wdtTimeOutAction, //
3443 "IdlePowerSaver/Enabled", patchParams.ipsEnable, //
3444 "IdlePowerSaver/EnterDwellTimeSeconds", patchParams.ipsEnterTime, //
3445 "IdlePowerSaver/EnterUtilizationPercent",
3446 patchParams.ipsEnterUtil, //
3447 "IdlePowerSaver/ExitDwellTimeSeconds", patchParams.ipsExitTime, //
3448 "IdlePowerSaver/ExitUtilizationPercent", patchParams.ipsExitUtil, //
3449 "IndicatorLED", patchParams.indicatorLed, //
3450 "LocationIndicatorActive", patchParams.locationIndicatorActive, //
3451 "PowerMode", patchParams.powerMode, //
3452 "PowerRestorePolicy", patchParams.powerRestorePolicy))
3453 {
3454 return;
3455 }
3456
3457 getComputerSystemIndex(asyncResp, systemName,
3458 std::bind_front(processComputerSystemPatch,
3459 asyncResp, systemName, patchParams));
3460}
3461
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003462inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003463 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003464 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003465 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003466{
3467 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3468 {
3469 return;
3470 }
3471 asyncResp->res.addHeader(
3472 boost::beast::http::field::link,
3473 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3474}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003475
3476/**
3477 * @brief Translates allowed host transitions to redfish string
3478 *
3479 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3480 * @param[out] allowableValues The translated host transition(s)
3481 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303482 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003483 * allowableValues. If translation not possible, does nothing to
3484 * allowableValues.
3485 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003486inline void dbusToRfAllowedHostTransitions(
3487 const std::string& dbusAllowedHostTran,
3488 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003489{
3490 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3491 {
3492 allowableValues.emplace_back(resource::ResetType::On);
3493 allowableValues.emplace_back(resource::ResetType::ForceOn);
3494 }
3495 else if (dbusAllowedHostTran ==
3496 "xyz.openbmc_project.State.Host.Transition.Off")
3497 {
3498 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3499 }
3500 else if (dbusAllowedHostTran ==
3501 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3502 {
3503 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3504 }
3505 else if (dbusAllowedHostTran ==
3506 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3507 {
3508 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3509 }
3510 else
3511 {
3512 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3513 }
3514}
3515
3516inline void afterGetAllowedHostTransitions(
3517 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3518 const boost::system::error_code& ec,
3519 const std::vector<std::string>& allowedHostTransitions)
3520{
3521 nlohmann::json::array_t allowableValues;
3522
3523 // Supported on all systems currently
3524 allowableValues.emplace_back(resource::ResetType::ForceOff);
3525 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3526 allowableValues.emplace_back(resource::ResetType::Nmi);
3527
3528 if (ec)
3529 {
Ed Tanouse715d142024-03-07 15:47:37 -08003530 if ((ec.value() ==
3531 boost::system::linux_error::bad_request_descriptor) ||
3532 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003533 {
3534 // Property not implemented so just return defaults
3535 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3536 allowableValues.emplace_back(resource::ResetType::On);
3537 allowableValues.emplace_back(resource::ResetType::ForceOn);
3538 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3539 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3540 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3541 }
3542 else
3543 {
3544 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3545 messages::internalError(asyncResp->res);
3546 return;
3547 }
3548 }
3549 else
3550 {
3551 for (const std::string& transition : allowedHostTransitions)
3552 {
3553 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3554 dbusToRfAllowedHostTransitions(transition, allowableValues);
3555 }
3556 }
3557
3558 nlohmann::json::object_t parameter;
3559 parameter["Name"] = "ResetType";
3560 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003561 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003562 parameter["AllowableValues"] = std::move(allowableValues);
3563 nlohmann::json::array_t parameters;
3564 parameters.emplace_back(std::move(parameter));
3565 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3566}
3567
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003568inline void getAllowedHostTransitions(
3569 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3570 const uint64_t computerSystemIndex)
3571{
3572 dbus::utility::getProperty<std::vector<std::string>>(
3573 getHostStateServiceName(computerSystemIndex),
3574 getHostStateObjectPath(computerSystemIndex),
3575 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
3576 std::bind_front(afterGetAllowedHostTransitions, asyncResp));
3577}
3578
Ed Tanousc1e219d2023-06-07 10:34:33 -07003579inline void handleSystemCollectionResetActionGet(
3580 crow::App& app, const crow::Request& req,
3581 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3582 const std::string& systemName)
3583{
3584 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3585 {
3586 return;
3587 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003588
Gunnar Mills68896202024-08-21 11:34:20 -05003589 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003590 {
Gunnar Mills68896202024-08-21 11:34:20 -05003591 if (systemName == "hypervisor")
3592 {
3593 handleHypervisorResetActionGet(asyncResp);
3594 return;
3595 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003596 }
3597
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003598 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003599 {
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003600 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3601 {
3602 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3603 systemName);
3604 return;
3605 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003606 }
3607
3608 asyncResp->res.addHeader(
3609 boost::beast::http::field::link,
3610 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3611
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003612 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3613 "/redfish/v1/Systems/{}/ResetActionInfo", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003614 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3615 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3616 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3617
Andrew Geissler33e1f122024-02-26 21:10:16 -06003618 // Look to see if system defines AllowedHostTransitions
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003619 getComputerSystemIndex(
3620 asyncResp, systemName,
3621 std::bind_front(getAllowedHostTransitions, asyncResp));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003622}
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003623
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303624/**
3625 * SystemResetActionInfo derived class for delivering Computer Systems
3626 * ResetType AllowableValues using ResetInfo schema.
3627 */
Ed Tanous100afe52023-06-07 13:30:46 -07003628inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303629{
Ed Tanous100afe52023-06-07 13:30:46 -07003630 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3631 .privileges(redfish::privileges::headComputerSystemCollection)
3632 .methods(boost::beast::http::verb::head)(
3633 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3634
3635 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3636 .privileges(redfish::privileges::getComputerSystemCollection)
3637 .methods(boost::beast::http::verb::get)(
3638 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3639
3640 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3641 .privileges(redfish::privileges::headComputerSystem)
3642 .methods(boost::beast::http::verb::head)(
3643 std::bind_front(handleComputerSystemHead, std::ref(app)));
3644
3645 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3646 .privileges(redfish::privileges::getComputerSystem)
3647 .methods(boost::beast::http::verb::get)(
3648 std::bind_front(handleComputerSystemGet, std::ref(app)));
3649
3650 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3651 .privileges(redfish::privileges::patchComputerSystem)
3652 .methods(boost::beast::http::verb::patch)(
3653 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3654
3655 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3656 .privileges(redfish::privileges::postComputerSystem)
3657 .methods(boost::beast::http::verb::post)(std::bind_front(
3658 handleComputerSystemResetActionPost, std::ref(app)));
3659
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003660 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003661 .privileges(redfish::privileges::headActionInfo)
3662 .methods(boost::beast::http::verb::head)(std::bind_front(
3663 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003664 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003665 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003666 .methods(boost::beast::http::verb::get)(std::bind_front(
3667 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003668}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003669} // namespace redfish