blob: 832c64405680f670156994cbe1238d98acc48667 [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.
Ed Tanous6c34de42018-08-29 13:37:36 -0700529 *
530 * @return None.
531 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700532inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700533{
Ed Tanous62598e32023-07-17 17:06:25 -0700534 BMCWEB_LOG_DEBUG("Get host information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800535 dbus::utility::getProperty<std::string>(
536 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
537 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700538 [asyncResp](const boost::system::error_code& ec,
539 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400540 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700541 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400542 if (ec == boost::system::errc::host_unreachable)
543 {
544 // Service not available, no error, just don't return
545 // host state info
546 BMCWEB_LOG_DEBUG("Service not available {}", ec);
547 return;
548 }
549 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
550 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700551 return;
552 }
Ed Tanous66173382018-08-15 18:20:59 -0700553
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400554 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
555 // Verify Host State
556 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
557 {
558 asyncResp->res.jsonValue["PowerState"] =
559 resource::PowerState::On;
560 asyncResp->res.jsonValue["Status"]["State"] =
561 resource::State::Enabled;
562 }
563 else if (hostState ==
564 "xyz.openbmc_project.State.Host.HostState.Quiesced")
565 {
566 asyncResp->res.jsonValue["PowerState"] =
567 resource::PowerState::On;
568 asyncResp->res.jsonValue["Status"]["State"] =
569 resource::State::Quiesced;
570 }
571 else if (hostState ==
572 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
573 {
574 asyncResp->res.jsonValue["PowerState"] =
575 resource::PowerState::On;
576 asyncResp->res.jsonValue["Status"]["State"] =
577 resource::State::InTest;
578 }
579 else if (
580 hostState ==
581 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
582 {
583 asyncResp->res.jsonValue["PowerState"] =
584 resource::PowerState::PoweringOn;
585 asyncResp->res.jsonValue["Status"]["State"] =
586 resource::State::Starting;
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
591 {
592 asyncResp->res.jsonValue["PowerState"] =
593 resource::PowerState::PoweringOff;
594 asyncResp->res.jsonValue["Status"]["State"] =
595 resource::State::Disabled;
596 }
597 else
598 {
599 asyncResp->res.jsonValue["PowerState"] =
600 resource::PowerState::Off;
601 asyncResp->res.jsonValue["Status"]["State"] =
602 resource::State::Disabled;
603 }
604 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700605}
606
607/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500608 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530609 *
610 * @param[in] dbusSource The boot source in DBUS speak.
611 *
612 * @return Returns as a string, the boot source in Redfish terms. If translation
613 * cannot be done, returns an empty string.
614 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000615inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530616{
617 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
618 {
619 return "None";
620 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700621 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530622 {
623 return "Hdd";
624 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700625 if (dbusSource ==
626 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530627 {
628 return "Cd";
629 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700630 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530631 {
632 return "Pxe";
633 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700634 if (dbusSource ==
635 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700636 {
637 return "Usb";
638 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700639 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530640}
641
642/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300643 * @brief Translates boot type DBUS property value to redfish.
644 *
645 * @param[in] dbusType The boot type in DBUS speak.
646 *
647 * @return Returns as a string, the boot type in Redfish terms. If translation
648 * cannot be done, returns an empty string.
649 */
650inline std::string dbusToRfBootType(const std::string& dbusType)
651{
652 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
653 {
654 return "Legacy";
655 }
656 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
657 {
658 return "UEFI";
659 }
660 return "";
661}
662
663/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500664 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530665 *
666 * @param[in] dbusMode The boot mode in DBUS speak.
667 *
668 * @return Returns as a string, the boot mode in Redfish terms. If translation
669 * cannot be done, returns an empty string.
670 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000671inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530672{
673 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
674 {
675 return "None";
676 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700677 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530678 {
679 return "Diags";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530682 {
683 return "BiosSetup";
684 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700685 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686}
687
688/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600689 * @brief Translates boot progress DBUS property value to redfish.
690 *
691 * @param[in] dbusBootProgress The boot progress in DBUS speak.
692 *
693 * @return Returns as a string, the boot progress in Redfish terms. If
694 * translation cannot be done, returns "None".
695 */
696inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
697{
698 // Now convert the D-Bus BootProgress to the appropriate Redfish
699 // enum
700 std::string rfBpLastState = "None";
701 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
702 "ProgressStages.Unspecified")
703 {
704 rfBpLastState = "None";
705 }
706 else if (dbusBootProgress ==
707 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
708 "PrimaryProcInit")
709 {
710 rfBpLastState = "PrimaryProcessorInitializationStarted";
711 }
712 else if (dbusBootProgress ==
713 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
714 "BusInit")
715 {
716 rfBpLastState = "BusInitializationStarted";
717 }
718 else if (dbusBootProgress ==
719 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
720 "MemoryInit")
721 {
722 rfBpLastState = "MemoryInitializationStarted";
723 }
724 else if (dbusBootProgress ==
725 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
726 "SecondaryProcInit")
727 {
728 rfBpLastState = "SecondaryProcessorInitializationStarted";
729 }
730 else if (dbusBootProgress ==
731 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
732 "PCIInit")
733 {
734 rfBpLastState = "PCIResourceConfigStarted";
735 }
736 else if (dbusBootProgress ==
737 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
738 "SystemSetup")
739 {
740 rfBpLastState = "SetupEntered";
741 }
742 else if (dbusBootProgress ==
743 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
744 "SystemInitComplete")
745 {
746 rfBpLastState = "SystemHardwareInitializationComplete";
747 }
748 else if (dbusBootProgress ==
749 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
750 "OSStart")
751 {
752 rfBpLastState = "OSBootStarted";
753 }
754 else if (dbusBootProgress ==
755 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
756 "OSRunning")
757 {
758 rfBpLastState = "OSRunning";
759 }
760 else
761 {
Ed Tanous62598e32023-07-17 17:06:25 -0700762 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600763 // Just return the default
764 }
765 return rfBpLastState;
766}
767
768/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500769 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530770 *
771 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700772 * @param[out] bootSource The DBus source
773 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700775 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530776 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400777inline int assignBootParameters(
778 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
779 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300781 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
782 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 if (rfSource == "None")
785 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700786 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700788 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
791 }
792 else if (rfSource == "Hdd")
793 {
794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
795 }
796 else if (rfSource == "Diags")
797 {
798 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
799 }
800 else if (rfSource == "Cd")
801 {
802 bootSource =
803 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
804 }
805 else if (rfSource == "BiosSetup")
806 {
807 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530808 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700809 else if (rfSource == "Usb")
810 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700811 bootSource =
812 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530814 else
815 {
Ed Tanous62598e32023-07-17 17:06:25 -0700816 BMCWEB_LOG_DEBUG(
817 "Invalid property value for BootSourceOverrideTarget: {}",
818 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700819 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700820 "BootSourceTargetOverride");
821 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530822 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530824}
Ali Ahmed19817712021-06-29 17:01:52 -0500825
Andrew Geissler978b8802020-11-19 13:36:40 -0600826/**
827 * @brief Retrieves boot progress of the system
828 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700829 * @param[in] asyncResp Shared pointer for generating response message.
Andrew Geissler978b8802020-11-19 13:36:40 -0600830 *
831 * @return None.
832 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700833inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600834{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800835 dbus::utility::getProperty<std::string>(
836 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700837 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700838 [asyncResp](const boost::system::error_code& ec,
839 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400840 if (ec)
841 {
842 // BootProgress is an optional object so just do nothing if
843 // not found
844 return;
845 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600846
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400847 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600848
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400849 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
850 dbusToRfBootProgress(bootProgressStr);
851 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600852}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530853
854/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000855 * @brief Retrieves boot progress Last Update of the system
856 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700857 * @param[in] asyncResp Shared pointer for generating response message.
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000858 *
859 * @return None.
860 */
861inline void getBootProgressLastStateTime(
Ed Tanousac106bf2023-06-07 09:24:59 -0700862 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000863{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800864 dbus::utility::getProperty<uint64_t>(
865 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000866 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700867 [asyncResp](const boost::system::error_code& ec,
868 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400869 if (ec)
870 {
871 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
872 return;
873 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000874
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400875 // BootProgressLastUpdate is the last time the BootProgress property
876 // was updated. The time is the Epoch time, number of microseconds
877 // since 1 Jan 1970 00::00::00 UTC."
878 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
879 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000880
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400881 // Convert to ISO 8601 standard
882 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
883 redfish::time_utils::getDateTimeUintUs(lastStateTime);
884 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000885}
886
887/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300888 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300889 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700890 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300891 *
892 * @return None.
893 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300894
Patrick Williams504af5a2025-02-03 14:29:03 -0500895inline void getBootOverrideType(
896 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300897{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800898 dbus::utility::getProperty<std::string>(
899 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700900 "/xyz/openbmc_project/control/host0/boot",
901 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700902 [asyncResp](const boost::system::error_code& ec,
903 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400904 if (ec)
905 {
906 // not an error, don't have to have the interface
907 return;
908 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300909
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400910 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300911
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400912 asyncResp->res
913 .jsonValue["Boot"]
914 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
915 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300916
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400917 auto rfType = dbusToRfBootType(bootType);
918 if (rfType.empty())
919 {
920 messages::internalError(asyncResp->res);
921 return;
922 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400924 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
925 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300926}
927
928/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300929 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530930 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700931 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530932 *
933 * @return None.
934 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300935
Patrick Williams504af5a2025-02-03 14:29:03 -0500936inline void getBootOverrideMode(
937 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800939 dbus::utility::getProperty<std::string>(
940 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700941 "/xyz/openbmc_project/control/host0/boot",
942 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700943 [asyncResp](const boost::system::error_code& ec,
944 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400945 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530946 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400947 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
948 messages::internalError(asyncResp->res);
949 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530950 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400951
952 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
953
954 nlohmann::json::array_t allowed;
955 allowed.emplace_back("None");
956 allowed.emplace_back("Pxe");
957 allowed.emplace_back("Hdd");
958 allowed.emplace_back("Cd");
959 allowed.emplace_back("Diags");
960 allowed.emplace_back("BiosSetup");
961 allowed.emplace_back("Usb");
962
963 asyncResp->res
964 .jsonValue["Boot"]
965 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
966 std::move(allowed);
967 if (bootModeStr !=
968 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
969 {
970 auto rfMode = dbusToRfBootMode(bootModeStr);
971 if (!rfMode.empty())
972 {
973 asyncResp->res
974 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
975 }
976 }
977 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530978}
979
980/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300981 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530982 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700983 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530984 *
985 * @return None.
986 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300987
Patrick Williams504af5a2025-02-03 14:29:03 -0500988inline void getBootOverrideSource(
989 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800991 dbus::utility::getProperty<std::string>(
992 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700993 "/xyz/openbmc_project/control/host0/boot",
994 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanousac106bf2023-06-07 09:24:59 -0700995 [asyncResp](const boost::system::error_code& ec,
996 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400997 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +0000998 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800999 // Service not available, no error, just don't return
1000 // Boot Override Source information
1001 if (ec.value() != EBADR &&
1002 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001003 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001004 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1005 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001006 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001007 return;
1008 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301009
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001010 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301011
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001012 auto rfSource = dbusToRfBootSource(bootSourceStr);
1013 if (!rfSource.empty())
1014 {
1015 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1016 rfSource;
1017 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001018
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001019 // Get BootMode as BootSourceOverrideTarget is constructed
1020 // from both BootSource and BootMode
1021 getBootOverrideMode(asyncResp);
1022 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301023}
1024
1025/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001026 * @brief This functions abstracts all the logic behind getting a
1027 * "BootSourceOverrideEnabled" property from an overall boot override enable
1028 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001030 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301031 *
1032 * @return None.
1033 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034
Ed Tanousac106bf2023-06-07 09:24:59 -07001035inline void processBootOverrideEnable(
1036 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1037 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001038{
1039 if (!bootOverrideEnableSetting)
1040 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001041 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1042 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 return;
1044 }
1045
1046 // If boot source override is enabled, we need to check 'one_time'
1047 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001048 dbus::utility::getProperty<bool>(
1049 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001050 "/xyz/openbmc_project/control/host0/boot/one_time",
1051 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001052 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001053 if (ec)
1054 {
1055 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1056 messages::internalError(asyncResp->res);
1057 return;
1058 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301059
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001060 if (oneTimeSetting)
1061 {
1062 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1063 "Once";
1064 }
1065 else
1066 {
1067 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1068 "Continuous";
1069 }
1070 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301071}
1072
1073/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074 * @brief Retrieves boot override enable over DBUS
1075 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001076 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001077 *
1078 * @return None.
1079 */
1080
Patrick Williams504af5a2025-02-03 14:29:03 -05001081inline void getBootOverrideEnable(
1082 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001083{
Ed Tanousdeae6a72024-11-11 21:58:57 -08001084 dbus::utility::getProperty<bool>(
1085 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001086 "/xyz/openbmc_project/control/host0/boot",
1087 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001088 [asyncResp](const boost::system::error_code& ec,
1089 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001090 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001091 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001092 // Service not available, no error, just don't return
1093 // Boot Override Enable information
1094 if (ec.value() != EBADR &&
1095 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001096 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001097 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1098 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001099 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001100 return;
1101 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001102
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001103 processBootOverrideEnable(asyncResp, bootOverrideEnable);
1104 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001105}
1106
1107/**
1108 * @brief Retrieves boot source override properties
1109 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001110 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001111 *
1112 * @return None.
1113 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001114inline void getBootProperties(
1115 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001116{
Ed Tanous62598e32023-07-17 17:06:25 -07001117 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001118
Ed Tanousac106bf2023-06-07 09:24:59 -07001119 getBootOverrideSource(asyncResp);
1120 getBootOverrideType(asyncResp);
1121 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001122}
1123
1124/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001125 * @brief Retrieves the Last Reset Time
1126 *
1127 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1128 * and power off. Even though this is the "system" Redfish object look at the
1129 * chassis D-Bus interface for the LastStateChangeTime since this has the
1130 * last power operation time.
1131 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001132 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001133 *
1134 * @return None.
1135 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001136inline void getLastResetTime(
1137 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001138{
Ed Tanous62598e32023-07-17 17:06:25 -07001139 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001140
Ed Tanousdeae6a72024-11-11 21:58:57 -08001141 dbus::utility::getProperty<uint64_t>(
1142 "xyz.openbmc_project.State.Chassis",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001143 "/xyz/openbmc_project/state/chassis0",
1144 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001145 [asyncResp](const boost::system::error_code& ec,
1146 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001147 if (ec)
1148 {
1149 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1150 return;
1151 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001152
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001153 // LastStateChangeTime is epoch time, in milliseconds
1154 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1155 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001156
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001157 // Convert to ISO 8601 standard
1158 asyncResp->res.jsonValue["LastResetTime"] =
1159 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1160 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001161}
1162
1163/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001164 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1165 *
1166 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1167 * corresponding property "AttemptsLeft" that keeps track of the amount of
1168 * automatic retry attempts left are hosted in phosphor-state-manager through
1169 * dbus.
1170 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001171 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001172 *
1173 * @return None.
1174 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001175inline void getAutomaticRebootAttempts(
1176 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001177{
Ed Tanous62598e32023-07-17 17:06:25 -07001178 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001179
Ed Tanousdeae6a72024-11-11 21:58:57 -08001180 dbus::utility::getAllProperties(
1181 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Corey Hardesty797d5da2022-04-26 17:54:52 +08001182 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001183 [asyncResp{asyncResp}](
1184 const boost::system::error_code& ec,
1185 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001186 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001187 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301188 if (ec.value() != EBADR &&
1189 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001190 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301191 // Service not available, no error, just don't return
1192 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001193 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1194 messages::internalError(asyncResp->res);
1195 }
1196 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001197 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001198
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001199 const uint32_t* attemptsLeft = nullptr;
1200 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001201
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001202 const bool success = sdbusplus::unpackPropertiesNoThrow(
1203 dbus_utils::UnpackErrorPrinter(), propertiesList,
1204 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001205
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001206 if (!success)
1207 {
1208 messages::internalError(asyncResp->res);
1209 return;
1210 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001211
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001212 if (attemptsLeft != nullptr)
1213 {
1214 asyncResp->res
1215 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1216 *attemptsLeft;
1217 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001218
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001219 if (retryAttempts != nullptr)
1220 {
1221 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1222 *retryAttempts;
1223 }
1224 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001225}
1226
1227/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001228 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1229 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001230 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001231 *
1232 * @return None.
1233 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001234inline void getAutomaticRetryPolicy(
1235 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001236{
Ed Tanous62598e32023-07-17 17:06:25 -07001237 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001238
Ed Tanousdeae6a72024-11-11 21:58:57 -08001239 dbus::utility::getProperty<bool>(
1240 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001241 "/xyz/openbmc_project/control/host0/auto_reboot",
1242 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001243 [asyncResp](const boost::system::error_code& ec,
1244 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001245 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001246 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301247 // Service not available, no error, just don't return
1248 // AutoReboot information
1249 if (ec.value() != EBADR &&
1250 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001251 {
1252 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1253 messages::internalError(asyncResp->res);
1254 }
1255 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001256 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001257
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001258 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1259 if (autoRebootEnabled)
1260 {
1261 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1262 "RetryAttempts";
1263 }
1264 else
1265 {
1266 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1267 "Disabled";
1268 }
1269 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001270
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001271 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1272 // and RetryAttempts. OpenBMC only supports Disabled and
1273 // RetryAttempts.
1274 nlohmann::json::array_t allowed;
1275 allowed.emplace_back("Disabled");
1276 allowed.emplace_back("RetryAttempts");
1277 asyncResp->res
1278 .jsonValue["Boot"]
1279 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1280 std::move(allowed);
1281 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001282}
1283
1284/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001285 * @brief Sets RetryAttempts
1286 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001287 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001288 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1289 *
1290 *@return None.
1291 */
1292
Ed Tanousac106bf2023-06-07 09:24:59 -07001293inline void setAutomaticRetryAttempts(
1294 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1295 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001296{
Ed Tanous62598e32023-07-17 17:06:25 -07001297 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001298 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301299 asyncResp, "Boot/AutomaticRetryAttempts",
1300 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001301 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001302 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301303 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001304}
1305
Ed Tanous8d69c662023-06-21 10:29:06 -07001306inline computer_system::PowerRestorePolicyTypes
1307 redfishPowerRestorePolicyFromDbus(std::string_view value)
1308{
1309 if (value ==
1310 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1311 {
1312 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1313 }
1314 if (value ==
1315 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1316 {
1317 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1318 }
1319 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001320 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001321 {
1322 return computer_system::PowerRestorePolicyTypes::LastState;
1323 }
1324 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1325 {
1326 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1327 }
1328 return computer_system::PowerRestorePolicyTypes::Invalid;
1329}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001330/**
George Liuc6a620f2020-04-10 17:18:11 +08001331 * @brief Retrieves power restore policy over DBUS.
1332 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001333 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001334 *
1335 * @return None.
1336 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001337inline void getPowerRestorePolicy(
1338 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001339{
Ed Tanous62598e32023-07-17 17:06:25 -07001340 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001341
Ed Tanousdeae6a72024-11-11 21:58:57 -08001342 dbus::utility::getProperty<std::string>(
1343 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001344 "/xyz/openbmc_project/control/host0/power_restore_policy",
1345 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001346 [asyncResp](const boost::system::error_code& ec,
1347 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001348 if (ec)
1349 {
1350 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1351 return;
1352 }
1353 computer_system::PowerRestorePolicyTypes restore =
1354 redfishPowerRestorePolicyFromDbus(policy);
1355 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1356 {
1357 messages::internalError(asyncResp->res);
1358 return;
1359 }
George Liuc6a620f2020-04-10 17:18:11 +08001360
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001361 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1362 });
George Liuc6a620f2020-04-10 17:18:11 +08001363}
1364
1365/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001366 * @brief Stop Boot On Fault over DBUS.
1367 *
1368 * @param[in] asyncResp Shared pointer for generating response message.
1369 *
1370 * @return None.
1371 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001372inline void getStopBootOnFault(
1373 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001374{
Ed Tanous62598e32023-07-17 17:06:25 -07001375 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001376
Ed Tanousdeae6a72024-11-11 21:58:57 -08001377 dbus::utility::getProperty<bool>(
1378 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001379 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1380 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001381 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001382 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301383 // Service not available, no error, just don't return
1384 // StopBootOnFault information
1385 if (ec.value() != EBADR ||
1386 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001387 {
1388 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1389 messages::internalError(asyncResp->res);
1390 }
1391 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001392 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001393
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001394 if (value)
1395 {
1396 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1397 computer_system::StopBootOnFault::AnyFault;
1398 }
1399 else
1400 {
1401 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1402 computer_system::StopBootOnFault::Never;
1403 }
1404 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001405}
1406
1407/**
Ali Ahmed19817712021-06-29 17:01:52 -05001408 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1409 * TPM is required for booting the host.
1410 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001411 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001412 *
1413 * @return None.
1414 */
1415inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001416 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001417{
Ed Tanous62598e32023-07-17 17:06:25 -07001418 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001419 constexpr std::array<std::string_view, 1> interfaces = {
1420 "xyz.openbmc_project.Control.TPM.Policy"};
1421 dbus::utility::getSubTree(
1422 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001423 [asyncResp](const boost::system::error_code& ec,
1424 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001425 if (ec)
Ali Ahmed19817712021-06-29 17:01:52 -05001426 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001427 BMCWEB_LOG_DEBUG(
1428 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1429 // This is an optional D-Bus object so just return if
1430 // error occurs
1431 return;
1432 }
1433 if (subtree.empty())
1434 {
1435 // As noted above, this is an optional interface so just return
1436 // if there is no instance found
1437 return;
1438 }
1439
1440 /* When there is more than one TPMEnable object... */
1441 if (subtree.size() > 1)
1442 {
1443 BMCWEB_LOG_DEBUG(
1444 "DBUS response has more than 1 TPM Enable object:{}",
1445 subtree.size());
1446 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001447 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001448 return;
1449 }
1450
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001451 // Make sure the Dbus response map has a service and objectPath
1452 // field
1453 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
Ali Ahmed19817712021-06-29 17:01:52 -05001454 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001455 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1456 messages::internalError(asyncResp->res);
1457 return;
Ali Ahmed19817712021-06-29 17:01:52 -05001458 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001459
1460 const std::string& path = subtree[0].first;
1461 const std::string& serv = subtree[0].second.begin()->first;
1462
1463 // Valid TPM Enable object found, now reading the current value
Ed Tanousdeae6a72024-11-11 21:58:57 -08001464 dbus::utility::getProperty<bool>(
1465 serv, path, "xyz.openbmc_project.Control.TPM.Policy",
1466 "TPMEnable",
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001467 [asyncResp](const boost::system::error_code& ec2,
1468 bool tpmRequired) {
1469 if (ec2)
1470 {
1471 BMCWEB_LOG_ERROR(
1472 "D-BUS response error on TPM.Policy Get{}", ec2);
1473 messages::internalError(asyncResp->res);
1474 return;
1475 }
1476
1477 if (tpmRequired)
1478 {
1479 asyncResp->res
1480 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1481 "Required";
1482 }
1483 else
1484 {
1485 asyncResp->res
1486 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1487 "Disabled";
1488 }
1489 });
George Liue99073f2022-12-09 11:06:16 +08001490 });
Ali Ahmed19817712021-06-29 17:01:52 -05001491}
1492
1493/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001494 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1495 * TPM is required for booting the host.
1496 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001497 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001498 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1499 *
1500 * @return None.
1501 */
1502inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001503 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001504{
Ed Tanous62598e32023-07-17 17:06:25 -07001505 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001506 constexpr std::array<std::string_view, 1> interfaces = {
1507 "xyz.openbmc_project.Control.TPM.Policy"};
1508 dbus::utility::getSubTree(
1509 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001510 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001511 tpmRequired](const boost::system::error_code& ec,
1512 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001513 if (ec)
1514 {
1515 BMCWEB_LOG_ERROR(
1516 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1517 messages::internalError(asyncResp->res);
1518 return;
1519 }
1520 if (subtree.empty())
1521 {
1522 messages::propertyValueNotInList(asyncResp->res,
1523 "ComputerSystem",
1524 "TrustedModuleRequiredToBoot");
1525 return;
1526 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001527
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001528 /* When there is more than one TPMEnable object... */
1529 if (subtree.size() > 1)
1530 {
1531 BMCWEB_LOG_DEBUG(
1532 "DBUS response has more than 1 TPM Enable object:{}",
1533 subtree.size());
1534 // Throw an internal Error and return
1535 messages::internalError(asyncResp->res);
1536 return;
1537 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001538
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001539 // Make sure the Dbus response map has a service and objectPath
1540 // field
1541 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1542 {
1543 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1544 messages::internalError(asyncResp->res);
1545 return;
1546 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001547
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001548 const std::string& path = subtree[0].first;
1549 const std::string& serv = subtree[0].second.begin()->first;
Ed Tanous002d39b2022-05-31 08:59:27 -07001550
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001551 if (serv.empty())
1552 {
1553 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1554 messages::internalError(asyncResp->res);
1555 return;
1556 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001557
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001558 // Valid TPM Enable object found, now setting the value
1559 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1560 path, "xyz.openbmc_project.Control.TPM.Policy",
1561 "TPMEnable", tpmRequired);
1562 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001563}
1564
1565/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301566 * @brief Sets boot properties into DBUS object(s).
1567 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001568 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001569 * @param[in] bootType The boot type to set.
1570 * @return Integer error code.
1571 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001572inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001573 const std::optional<std::string>& bootType)
1574{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001575 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001576
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001577 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001578 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001579 return;
1580 }
1581
1582 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001583 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001584 // Figure out which DBUS interface and property to use
1585 if (*bootType == "Legacy")
1586 {
1587 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1588 }
1589 else if (*bootType == "UEFI")
1590 {
1591 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1592 }
1593 else
1594 {
Ed Tanous62598e32023-07-17 17:06:25 -07001595 BMCWEB_LOG_DEBUG("Invalid property value for "
1596 "BootSourceOverrideMode: {}",
1597 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001598 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001599 "BootSourceOverrideMode");
1600 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001601 }
1602
1603 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001604 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001605
Ginu Georgee93abac2024-06-14 17:35:27 +05301606 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1607 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001608 sdbusplus::message::object_path(
1609 "/xyz/openbmc_project/control/host0/boot"),
1610 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301611 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001612}
1613
1614/**
1615 * @brief Sets boot properties into DBUS object(s).
1616 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001617 * @param[in] asyncResp Shared pointer for generating response
1618 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001619 * @param[in] bootType The boot type to set.
1620 * @return Integer error code.
1621 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001622inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001623 const std::optional<std::string>& bootEnable)
1624{
1625 if (!bootEnable)
1626 {
1627 return;
1628 }
1629 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001630 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001631
1632 bool bootOverrideEnable = false;
1633 bool bootOverridePersistent = false;
1634 // Figure out which DBUS interface and property to use
1635 if (*bootEnable == "Disabled")
1636 {
1637 bootOverrideEnable = false;
1638 }
1639 else if (*bootEnable == "Once")
1640 {
1641 bootOverrideEnable = true;
1642 bootOverridePersistent = false;
1643 }
1644 else if (*bootEnable == "Continuous")
1645 {
1646 bootOverrideEnable = true;
1647 bootOverridePersistent = true;
1648 }
1649 else
1650 {
Ed Tanous62598e32023-07-17 17:06:25 -07001651 BMCWEB_LOG_DEBUG(
1652 "Invalid property value for BootSourceOverrideEnabled: {}",
1653 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001654 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001655 "BootSourceOverrideEnabled");
1656 return;
1657 }
1658
1659 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001660 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001661
Ginu Georgee93abac2024-06-14 17:35:27 +05301662 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1663 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001664 sdbusplus::message::object_path(
1665 "/xyz/openbmc_project/control/host0/boot"),
1666 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301667 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001668
1669 if (!bootOverrideEnable)
1670 {
1671 return;
1672 }
1673
1674 // In case boot override is enabled we need to set correct value for the
1675 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001676 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1677 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001678
Ginu Georgee93abac2024-06-14 17:35:27 +05301679 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1680 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001681 sdbusplus::message::object_path(
1682 "/xyz/openbmc_project/control/host0/boot/one_time"),
1683 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301684 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +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 message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301691 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301692 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001693 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301694 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001695inline void setBootModeOrSource(
1696 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1697 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301698{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001699 std::string bootSourceStr;
1700 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001701
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001702 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301703 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001704 return;
1705 }
1706
1707 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001708 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001709 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001710 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1711 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001712 {
Ed Tanous62598e32023-07-17 17:06:25 -07001713 BMCWEB_LOG_DEBUG(
1714 "Invalid property value for BootSourceOverrideTarget: {}",
1715 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001716 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001717 "BootSourceTargetOverride");
1718 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001719 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301720
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001721 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001722 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1723 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001724
Ginu Georgee93abac2024-06-14 17:35:27 +05301725 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1726 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001727 sdbusplus::message::object_path(
1728 "/xyz/openbmc_project/control/host0/boot"),
1729 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301730 bootSourceStr);
1731 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1732 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001733 sdbusplus::message::object_path(
1734 "/xyz/openbmc_project/control/host0/boot"),
1735 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301736 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001737}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001738
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001739/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001740 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301741 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001742 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301743 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001744 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301745 * @param[in] bootEnable The boot override enable from incoming RF request.
1746 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001747 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301748 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001749
Patrick Williams504af5a2025-02-03 14:29:03 -05001750inline void setBootProperties(
1751 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1752 const std::optional<std::string>& bootSource,
1753 const std::optional<std::string>& bootType,
1754 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301755{
Ed Tanous62598e32023-07-17 17:06:25 -07001756 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301757
Ed Tanousac106bf2023-06-07 09:24:59 -07001758 setBootModeOrSource(asyncResp, bootSource);
1759 setBootType(asyncResp, bootType);
1760 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301761}
1762
George Liuc6a620f2020-04-10 17:18:11 +08001763/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001764 * @brief Sets AssetTag
1765 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001766 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001767 * @param[in] assetTag "AssetTag" from request.
1768 *
1769 * @return None.
1770 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001771inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001772 const std::string& assetTag)
1773{
George Liue99073f2022-12-09 11:06:16 +08001774 constexpr std::array<std::string_view, 1> interfaces = {
1775 "xyz.openbmc_project.Inventory.Item.System"};
1776 dbus::utility::getSubTree(
1777 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001778 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001779 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001780 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001781 if (ec)
1782 {
1783 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1784 messages::internalError(asyncResp->res);
1785 return;
1786 }
1787 if (subtree.empty())
1788 {
1789 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1790 messages::internalError(asyncResp->res);
1791 return;
1792 }
1793 // Assume only 1 system D-Bus object
1794 // Throw an error if there is more than 1
1795 if (subtree.size() > 1)
1796 {
1797 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1798 messages::internalError(asyncResp->res);
1799 return;
1800 }
1801 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1802 {
1803 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1804 messages::internalError(asyncResp->res);
1805 return;
1806 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001807
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001808 const std::string& path = subtree[0].first;
1809 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001810
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001811 if (service.empty())
1812 {
1813 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1814 messages::internalError(asyncResp->res);
1815 return;
1816 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001817
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001818 setDbusProperty(asyncResp, "AssetTag", service, path,
1819 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1820 "AssetTag", assetTag);
1821 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001822}
1823
1824/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001825 * @brief Validate the specified stopBootOnFault is valid and return the
1826 * stopBootOnFault name associated with that string
1827 *
1828 * @param[in] stopBootOnFaultString String representing the desired
1829 * stopBootOnFault
1830 *
1831 * @return stopBootOnFault value or empty if incoming value is not valid
1832 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001833inline std::optional<bool> validstopBootOnFault(
1834 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001835{
1836 if (stopBootOnFaultString == "AnyFault")
1837 {
1838 return true;
1839 }
1840
1841 if (stopBootOnFaultString == "Never")
1842 {
1843 return false;
1844 }
1845
1846 return std::nullopt;
1847}
1848
1849/**
1850 * @brief Sets stopBootOnFault
1851 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001852 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001853 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1854 *
1855 * @return None.
1856 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001857inline void setStopBootOnFault(
1858 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1859 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001860{
Ed Tanous62598e32023-07-17 17:06:25 -07001861 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001862
1863 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1864 if (!stopBootEnabled)
1865 {
Ed Tanous62598e32023-07-17 17:06:25 -07001866 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1867 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001868 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001869 "StopBootOnFault");
1870 return;
1871 }
1872
Ginu Georgee93abac2024-06-14 17:35:27 +05301873 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1874 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001875 sdbusplus::message::object_path(
1876 "/xyz/openbmc_project/logging/settings"),
1877 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301878 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001879}
1880
1881/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001882 * @brief Sets automaticRetry (Auto Reboot)
1883 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001884 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001885 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1886 *
1887 * @return None.
1888 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001889inline void setAutomaticRetry(
1890 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1891 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001892{
Ed Tanous62598e32023-07-17 17:06:25 -07001893 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001894
1895 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001896 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001897
1898 if (automaticRetryConfig == "Disabled")
1899 {
1900 autoRebootEnabled = false;
1901 }
1902 else if (automaticRetryConfig == "RetryAttempts")
1903 {
1904 autoRebootEnabled = true;
1905 }
1906 else
1907 {
Ed Tanous62598e32023-07-17 17:06:25 -07001908 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1909 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001910 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001911 "AutomaticRetryConfig");
1912 return;
1913 }
1914
Ginu Georgee93abac2024-06-14 17:35:27 +05301915 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1916 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001917 sdbusplus::message::object_path(
1918 "/xyz/openbmc_project/control/host0/auto_reboot"),
1919 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301920 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001921}
1922
Ed Tanous8d69c662023-06-21 10:29:06 -07001923inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1924{
1925 if (policy == "AlwaysOn")
1926 {
1927 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1928 }
1929 if (policy == "AlwaysOff")
1930 {
1931 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1932 }
1933 if (policy == "LastState")
1934 {
1935 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1936 }
1937 return "";
1938}
1939
Gunnar Mills69f35302020-05-17 16:06:31 -05001940/**
George Liuc6a620f2020-04-10 17:18:11 +08001941 * @brief Sets power restore policy properties.
1942 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001943 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001944 * @param[in] policy power restore policy properties from request.
1945 *
1946 * @return None.
1947 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001948inline void setPowerRestorePolicy(
1949 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1950 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001951{
Ed Tanous62598e32023-07-17 17:06:25 -07001952 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001953
Ed Tanous8d69c662023-06-21 10:29:06 -07001954 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001955
Ed Tanous8d69c662023-06-21 10:29:06 -07001956 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001957 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001958 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001959 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001960 return;
1961 }
1962
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001963 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301964 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001965 sdbusplus::message::object_path(
1966 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001967 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301968 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001969}
1970
AppaRao Pulia6349912019-10-18 17:16:08 +05301971/**
1972 * @brief Retrieves provisioning status
1973 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001974 * @param[in] asyncResp Shared pointer for completing asynchronous
1975 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301976 *
1977 * @return None.
1978 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001979inline void getProvisioningStatus(
1980 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301981{
Ed Tanous62598e32023-07-17 17:06:25 -07001982 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08001983 dbus::utility::getAllProperties(
1984 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1985 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001986 [asyncResp](const boost::system::error_code& ec,
1987 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001988 nlohmann::json& oemPFR =
1989 asyncResp->res
1990 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1991 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1992 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1993 oemPFR["@odata.type"] =
1994 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001995
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001996 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05301997 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001998 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1999 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002000 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002001 FirmwareProvisioningStatus::NotProvisioned;
2002 return;
2003 }
2004
2005 const bool* provState = nullptr;
2006 const bool* lockState = nullptr;
2007
2008 const bool success = sdbusplus::unpackPropertiesNoThrow(
2009 dbus_utils::UnpackErrorPrinter(), propertiesList,
2010 "UfmProvisioned", provState, "UfmLocked", lockState);
2011
2012 if (!success)
2013 {
2014 messages::internalError(asyncResp->res);
2015 return;
2016 }
2017
2018 if ((provState == nullptr) || (lockState == nullptr))
2019 {
2020 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2021 messages::internalError(asyncResp->res);
2022 return;
2023 }
2024
2025 if (*provState)
2026 {
2027 if (*lockState)
2028 {
2029 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2030 FirmwareProvisioningStatus::ProvisionedAndLocked;
2031 }
2032 else
2033 {
2034 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2035 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2036 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302037 }
2038 else
2039 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002040 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002041 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302042 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002043 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302044}
AppaRao Pulia6349912019-10-18 17:16:08 +05302045
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302046/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002047 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002048 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002049 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002050 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002051 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002052 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002053inline computer_system::PowerMode translatePowerModeString(
2054 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002055{
Chris Cainb6655102024-02-01 14:35:33 -06002056 using PowerMode = computer_system::PowerMode;
2057
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002058 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002059 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002060 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002061 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002062 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002063 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002064 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002065 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002066 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002067 if (modeString ==
2068 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002069 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002070 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002071 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002072 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002073 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2074 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002075 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002076 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002077 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002078 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2079 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002080 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002081 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002082 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002083 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2084 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002085 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002086 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002087 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002088 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002089 return PowerMode::OEM;
2090 }
2091 // Any other values would be invalid
2092 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2093 return PowerMode::Invalid;
2094}
2095
Patrick Williams504af5a2025-02-03 14:29:03 -05002096inline void afterGetPowerMode(
2097 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2098 const boost::system::error_code& ec,
2099 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002100{
2101 if (ec)
2102 {
2103 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2104 messages::internalError(asyncResp->res);
2105 return;
2106 }
2107
2108 std::string powerMode;
2109 const std::vector<std::string>* allowedModes = nullptr;
2110 const bool success = sdbusplus::unpackPropertiesNoThrow(
2111 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2112 "AllowedPowerModes", allowedModes);
2113
2114 if (!success)
2115 {
2116 messages::internalError(asyncResp->res);
2117 return;
2118 }
2119
2120 nlohmann::json::array_t modeList;
2121 if (allowedModes == nullptr)
2122 {
2123 modeList.emplace_back("Static");
2124 modeList.emplace_back("MaximumPerformance");
2125 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002126 }
2127 else
2128 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002129 for (const auto& aMode : *allowedModes)
2130 {
2131 computer_system::PowerMode modeValue =
2132 translatePowerModeString(aMode);
2133 if (modeValue == computer_system::PowerMode::Invalid)
2134 {
2135 messages::internalError(asyncResp->res);
2136 continue;
2137 }
2138 modeList.emplace_back(modeValue);
2139 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002140 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002141 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002142
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002143 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2144 const computer_system::PowerMode modeValue =
2145 translatePowerModeString(powerMode);
2146 if (modeValue == computer_system::PowerMode::Invalid)
2147 {
2148 messages::internalError(asyncResp->res);
2149 return;
2150 }
2151 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2152}
Chris Cain3a2d04242021-05-28 16:57:10 -05002153/**
2154 * @brief Retrieves system power mode
2155 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002156 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002157 *
2158 * @return None.
2159 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002160inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002161{
Ed Tanous62598e32023-07-17 17:06:25 -07002162 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002163
2164 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002165 constexpr std::array<std::string_view, 1> interfaces = {
2166 "xyz.openbmc_project.Control.Power.Mode"};
2167 dbus::utility::getSubTree(
2168 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002169 [asyncResp](const boost::system::error_code& ec,
2170 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002171 if (ec)
2172 {
2173 BMCWEB_LOG_DEBUG(
2174 "DBUS response error on Power.Mode GetSubTree {}", ec);
2175 // This is an optional D-Bus object so just return if
2176 // error occurs
2177 return;
2178 }
2179 if (subtree.empty())
2180 {
2181 // As noted above, this is an optional interface so just return
2182 // if there is no instance found
2183 return;
2184 }
2185 if (subtree.size() > 1)
2186 {
2187 // More then one PowerMode object is not supported and is an
2188 // error
2189 BMCWEB_LOG_DEBUG(
2190 "Found more than 1 system D-Bus Power.Mode objects: {}",
2191 subtree.size());
2192 messages::internalError(asyncResp->res);
2193 return;
2194 }
2195 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2196 {
2197 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2198 messages::internalError(asyncResp->res);
2199 return;
2200 }
2201 const std::string& path = subtree[0].first;
2202 const std::string& service = subtree[0].second.begin()->first;
2203 if (service.empty())
2204 {
2205 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2206 messages::internalError(asyncResp->res);
2207 return;
2208 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002209
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002210 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002211 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002212 *crow::connections::systemBus, service, path,
2213 "xyz.openbmc_project.Control.Power.Mode",
2214 [asyncResp](
2215 const boost::system::error_code& ec2,
2216 const dbus::utility::DBusPropertiesMap& properties) {
2217 afterGetPowerMode(asyncResp, ec2, properties);
2218 });
George Liue99073f2022-12-09 11:06:16 +08002219 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002220}
2221
2222/**
2223 * @brief Validate the specified mode is valid and return the PowerMode
2224 * name associated with that string
2225 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002226 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002227 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002228 *
2229 * @return PowerMode value or empty string if mode is not valid
2230 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002231inline std::string validatePowerMode(
2232 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2233 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002234{
Chris Cainb6655102024-02-01 14:35:33 -06002235 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002236 std::string mode;
2237
Chris Cainb6655102024-02-01 14:35:33 -06002238 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002239 {
2240 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2241 }
Chris Cainb6655102024-02-01 14:35:33 -06002242 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002243 {
George Liu0fda0f12021-11-16 10:06:17 +08002244 mode =
2245 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002246 }
Chris Cainb6655102024-02-01 14:35:33 -06002247 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002248 {
2249 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2250 }
Chris Cainb6655102024-02-01 14:35:33 -06002251 else if (modeValue == PowerMode::BalancedPerformance)
2252 {
2253 mode =
2254 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2255 }
2256 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2257 {
2258 mode =
2259 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2260 }
2261 else if (modeValue == PowerMode::EfficiencyFavorPower)
2262 {
2263 mode =
2264 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2265 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002266 else
2267 {
Chris Cainb6655102024-02-01 14:35:33 -06002268 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002269 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002270 }
2271 return mode;
2272}
2273
2274/**
2275 * @brief Sets system power mode.
2276 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002277 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002278 * @param[in] pmode System power mode from request.
2279 *
2280 * @return None.
2281 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002282inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002283 const std::string& pmode)
2284{
Ed Tanous62598e32023-07-17 17:06:25 -07002285 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002286
Ed Tanousac106bf2023-06-07 09:24:59 -07002287 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002288 if (powerMode.empty())
2289 {
2290 return;
2291 }
2292
2293 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002294 constexpr std::array<std::string_view, 1> interfaces = {
2295 "xyz.openbmc_project.Control.Power.Mode"};
2296 dbus::utility::getSubTree(
2297 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002298 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002299 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002300 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002301 if (ec)
2302 {
2303 BMCWEB_LOG_ERROR(
2304 "DBUS response error on Power.Mode GetSubTree {}", ec);
2305 // This is an optional D-Bus object, but user attempted to patch
2306 messages::internalError(asyncResp->res);
2307 return;
2308 }
2309 if (subtree.empty())
2310 {
2311 // This is an optional D-Bus object, but user attempted to patch
2312 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2313 "PowerMode");
2314 return;
2315 }
2316 if (subtree.size() > 1)
2317 {
2318 // More then one PowerMode object is not supported and is an
2319 // error
2320 BMCWEB_LOG_DEBUG(
2321 "Found more than 1 system D-Bus Power.Mode objects: {}",
2322 subtree.size());
2323 messages::internalError(asyncResp->res);
2324 return;
2325 }
2326 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2327 {
2328 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2329 messages::internalError(asyncResp->res);
2330 return;
2331 }
2332 const std::string& path = subtree[0].first;
2333 const std::string& service = subtree[0].second.begin()->first;
2334 if (service.empty())
2335 {
2336 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2337 messages::internalError(asyncResp->res);
2338 return;
2339 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002340
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002341 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002342
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002343 // Set the Power Mode property
2344 setDbusProperty(asyncResp, "PowerMode", service, path,
2345 "xyz.openbmc_project.Control.Power.Mode",
2346 "PowerMode", powerMode);
2347 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002348}
2349
2350/**
Yong Li51709ff2019-09-30 14:13:04 +08002351 * @brief Translates watchdog timeout action DBUS property value to redfish.
2352 *
2353 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2354 *
2355 * @return Returns as a string, the timeout action in Redfish terms. If
2356 * translation cannot be done, returns an empty string.
2357 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002358inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002359{
2360 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2361 {
2362 return "None";
2363 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002364 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002365 {
2366 return "ResetSystem";
2367 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002368 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002369 {
2370 return "PowerDown";
2371 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002372 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002373 {
2374 return "PowerCycle";
2375 }
2376
2377 return "";
2378}
2379
2380/**
Yong Lic45f0082019-10-10 14:19:01 +08002381 *@brief Translates timeout action from Redfish to DBUS property value.
2382 *
2383 *@param[in] rfAction The timeout action in Redfish.
2384 *
2385 *@return Returns as a string, the time_out action as expected by DBUS.
2386 *If translation cannot be done, returns an empty string.
2387 */
2388
Ed Tanous23a21a12020-07-25 04:45:05 +00002389inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002390{
2391 if (rfAction == "None")
2392 {
2393 return "xyz.openbmc_project.State.Watchdog.Action.None";
2394 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002395 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002396 {
2397 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2398 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002399 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002400 {
2401 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2402 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002403 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002404 {
2405 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2406 }
2407
2408 return "";
2409}
2410
2411/**
Yong Li51709ff2019-09-30 14:13:04 +08002412 * @brief Retrieves host watchdog timer properties over DBUS
2413 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002414 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002415 *
2416 * @return None.
2417 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002418inline void getHostWatchdogTimer(
2419 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002420{
Ed Tanous62598e32023-07-17 17:06:25 -07002421 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002422 dbus::utility::getAllProperties(
2423 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002424 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002425 [asyncResp](const boost::system::error_code& ec,
2426 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002427 if (ec)
2428 {
2429 // watchdog service is stopped
2430 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2431 return;
2432 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002433
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002434 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002435
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002436 nlohmann::json& hostWatchdogTimer =
2437 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002438
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002439 // watchdog service is running/enabled
2440 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002441
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002442 const bool* enabled = nullptr;
2443 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002444
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002445 const bool success = sdbusplus::unpackPropertiesNoThrow(
2446 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2447 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002448
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002449 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002450 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002451 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002452 return;
2453 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002454
2455 if (enabled != nullptr)
2456 {
2457 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2458 }
2459
2460 if (expireAction != nullptr)
2461 {
2462 std::string action = dbusToRfWatchdogAction(*expireAction);
2463 if (action.empty())
2464 {
2465 messages::internalError(asyncResp->res);
2466 return;
2467 }
2468 hostWatchdogTimer["TimeoutAction"] = action;
2469 }
2470 });
Yong Li51709ff2019-09-30 14:13:04 +08002471}
2472
2473/**
Yong Lic45f0082019-10-10 14:19:01 +08002474 * @brief Sets Host WatchDog Timer properties.
2475 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002476 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002477 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2478 * RF request.
2479 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2480 *
2481 * @return None.
2482 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002483inline void setWDTProperties(
2484 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2485 const std::optional<bool> wdtEnable,
2486 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002487{
Ed Tanous62598e32023-07-17 17:06:25 -07002488 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002489
2490 if (wdtTimeOutAction)
2491 {
2492 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2493 // check if TimeOut Action is Valid
2494 if (wdtTimeOutActStr.empty())
2495 {
Ed Tanous62598e32023-07-17 17:06:25 -07002496 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2497 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002498 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002499 "TimeoutAction");
2500 return;
2501 }
2502
Ginu Georgee93abac2024-06-14 17:35:27 +05302503 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2504 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002505 sdbusplus::message::object_path(
2506 "/xyz/openbmc_project/watchdog/host0"),
2507 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302508 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002509 }
2510
2511 if (wdtEnable)
2512 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302513 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2514 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002515 sdbusplus::message::object_path(
2516 "/xyz/openbmc_project/watchdog/host0"),
2517 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302518 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002519 }
2520}
2521
Chris Cain37bbf982021-09-20 10:53:09 -05002522/**
2523 * @brief Parse the Idle Power Saver properties into json
2524 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002525 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002526 * @param[in] properties IPS property data from DBus.
2527 *
2528 * @return true if successful
2529 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002530inline bool parseIpsProperties(
2531 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2532 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002533{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002534 const bool* enabled = nullptr;
2535 const uint8_t* enterUtilizationPercent = nullptr;
2536 const uint64_t* enterDwellTime = nullptr;
2537 const uint8_t* exitUtilizationPercent = nullptr;
2538 const uint64_t* exitDwellTime = nullptr;
2539
2540 const bool success = sdbusplus::unpackPropertiesNoThrow(
2541 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002542 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2543 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2544 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002545
2546 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002547 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002548 return false;
2549 }
2550
2551 if (enabled != nullptr)
2552 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002553 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002554 }
2555
2556 if (enterUtilizationPercent != nullptr)
2557 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002558 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002559 *enterUtilizationPercent;
2560 }
2561
2562 if (enterDwellTime != nullptr)
2563 {
2564 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002565 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002566 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2567 .count();
2568 }
2569
2570 if (exitUtilizationPercent != nullptr)
2571 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002572 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002573 *exitUtilizationPercent;
2574 }
2575
2576 if (exitDwellTime != nullptr)
2577 {
2578 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002579 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002580 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2581 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002582 }
2583
2584 return true;
2585}
2586
2587/**
2588 * @brief Retrieves host watchdog timer properties over DBUS
2589 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002590 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002591 *
2592 * @return None.
2593 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002594inline void getIdlePowerSaver(
2595 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002596{
Ed Tanous62598e32023-07-17 17:06:25 -07002597 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002598
2599 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002600 constexpr std::array<std::string_view, 1> interfaces = {
2601 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2602 dbus::utility::getSubTree(
2603 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002604 [asyncResp](const boost::system::error_code& ec,
2605 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002606 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002607 {
Ed Tanous62598e32023-07-17 17:06:25 -07002608 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002609 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2610 ec);
2611 messages::internalError(asyncResp->res);
2612 return;
2613 }
2614 if (subtree.empty())
2615 {
2616 // This is an optional interface so just return
2617 // if there is no instance found
2618 BMCWEB_LOG_DEBUG("No instances found");
2619 return;
2620 }
2621 if (subtree.size() > 1)
2622 {
2623 // More then one PowerIdlePowerSaver object is not supported and
2624 // is an error
2625 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2626 "Power.IdlePowerSaver objects: {}",
2627 subtree.size());
2628 messages::internalError(asyncResp->res);
2629 return;
2630 }
2631 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2632 {
2633 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2634 messages::internalError(asyncResp->res);
2635 return;
2636 }
2637 const std::string& path = subtree[0].first;
2638 const std::string& service = subtree[0].second.begin()->first;
2639 if (service.empty())
2640 {
2641 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002642 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002643 return;
2644 }
2645
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002646 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002647 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002648 *crow::connections::systemBus, service, path,
2649 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2650 [asyncResp](
2651 const boost::system::error_code& ec2,
2652 const dbus::utility::DBusPropertiesMap& properties) {
2653 if (ec2)
2654 {
2655 BMCWEB_LOG_ERROR(
2656 "DBUS response error on IdlePowerSaver GetAll: {}",
2657 ec2);
2658 messages::internalError(asyncResp->res);
2659 return;
2660 }
2661
2662 if (!parseIpsProperties(asyncResp, properties))
2663 {
2664 messages::internalError(asyncResp->res);
2665 return;
2666 }
2667 });
George Liue99073f2022-12-09 11:06:16 +08002668 });
Chris Cain37bbf982021-09-20 10:53:09 -05002669
Ed Tanous62598e32023-07-17 17:06:25 -07002670 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002671}
2672
2673/**
2674 * @brief Sets Idle Power Saver properties.
2675 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002676 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002677 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2678 * RF request.
2679 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2680 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2681 * before entering idle state.
2682 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2683 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2684 * before exiting idle state
2685 *
2686 * @return None.
2687 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002688inline void setIdlePowerSaver(
2689 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2690 const std::optional<bool> ipsEnable,
2691 const std::optional<uint8_t> ipsEnterUtil,
2692 const std::optional<uint64_t> ipsEnterTime,
2693 const std::optional<uint8_t> ipsExitUtil,
2694 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002695{
Ed Tanous62598e32023-07-17 17:06:25 -07002696 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002697
2698 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002699 constexpr std::array<std::string_view, 1> interfaces = {
2700 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2701 dbus::utility::getSubTree(
2702 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002703 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002704 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002705 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002706 if (ec)
2707 {
2708 BMCWEB_LOG_ERROR(
2709 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2710 ec);
2711 messages::internalError(asyncResp->res);
2712 return;
2713 }
2714 if (subtree.empty())
2715 {
2716 // This is an optional D-Bus object, but user attempted to patch
2717 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2718 "IdlePowerSaver");
2719 return;
2720 }
2721 if (subtree.size() > 1)
2722 {
2723 // More then one PowerIdlePowerSaver object is not supported and
2724 // is an error
2725 BMCWEB_LOG_DEBUG(
2726 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2727 subtree.size());
2728 messages::internalError(asyncResp->res);
2729 return;
2730 }
2731 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2732 {
2733 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2734 messages::internalError(asyncResp->res);
2735 return;
2736 }
2737 const std::string& path = subtree[0].first;
2738 const std::string& service = subtree[0].second.begin()->first;
2739 if (service.empty())
2740 {
2741 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2742 messages::internalError(asyncResp->res);
2743 return;
2744 }
Chris Cain37bbf982021-09-20 10:53:09 -05002745
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002746 // Valid Power IdlePowerSaver object found, now set any values that
2747 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002748
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002749 if (ipsEnable)
2750 {
2751 setDbusProperty(
2752 asyncResp, "IdlePowerSaver/Enabled", service, path,
2753 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2754 "Enabled", *ipsEnable);
2755 }
2756 if (ipsEnterUtil)
2757 {
2758 setDbusProperty(
2759 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2760 service, path,
2761 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2762 "EnterUtilizationPercent", *ipsEnterUtil);
2763 }
2764 if (ipsEnterTime)
2765 {
2766 // Convert from seconds into milliseconds for DBus
2767 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2768 setDbusProperty(
2769 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2770 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2771 "EnterDwellTime", timeMilliseconds);
2772 }
2773 if (ipsExitUtil)
2774 {
2775 setDbusProperty(
2776 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2777 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2778 "ExitUtilizationPercent", *ipsExitUtil);
2779 }
2780 if (ipsExitTime)
2781 {
2782 // Convert from seconds into milliseconds for DBus
2783 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2784 setDbusProperty(
2785 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2786 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2787 "ExitDwellTime", timeMilliseconds);
2788 }
2789 });
Chris Cain37bbf982021-09-20 10:53:09 -05002790
Ed Tanous62598e32023-07-17 17:06:25 -07002791 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002792}
2793
Ed Tanousc1e219d2023-06-07 10:34:33 -07002794inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002795 crow::App& app, const crow::Request& req,
2796 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2797{
2798 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2799 {
2800 return;
2801 }
2802 asyncResp->res.addHeader(
2803 boost::beast::http::field::link,
2804 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2805}
2806
Ed Tanousc1e219d2023-06-07 10:34:33 -07002807inline void handleComputerSystemCollectionGet(
2808 crow::App& app, const crow::Request& req,
2809 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2810{
2811 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2812 {
2813 return;
2814 }
2815
2816 asyncResp->res.addHeader(
2817 boost::beast::http::field::link,
2818 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2819 asyncResp->res.jsonValue["@odata.type"] =
2820 "#ComputerSystemCollection.ComputerSystemCollection";
2821 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2822 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2823
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002824 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002825}
2826
Yong Lic45f0082019-10-10 14:19:01 +08002827/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002828 * Function transceives data with dbus directly.
2829 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002830inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831{
Patrick Williams89492a12023-05-10 07:51:34 -05002832 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2833 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2834 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002835 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002836 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002837
Ed Tanous177612a2025-02-14 15:16:09 -08002838 dbus::utility::async_method_call(
2839 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002840 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002841 if (ec)
2842 {
2843 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2844 messages::internalError(asyncResp->res);
2845 return;
2846 }
2847 messages::success(asyncResp->res);
2848 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002849 serviceName, objectPath, interfaceName, method);
2850}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002851
Ed Tanousc1e219d2023-06-07 10:34:33 -07002852inline void handleComputerSystemResetActionPost(
2853 crow::App& app, const crow::Request& req,
2854 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2855 const std::string& systemName)
2856{
2857 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2858 {
2859 return;
2860 }
Gunnar Millsdd7090e2024-07-30 15:23:05 -05002861
2862 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2863 {
2864 if (systemName == "hypervisor")
2865 {
2866 handleHypervisorSystemResetPost(req, asyncResp);
2867 return;
2868 }
2869 }
2870
Ed Tanous253f11b2024-05-16 09:38:31 -07002871 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002872 {
2873 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2874 systemName);
2875 return;
2876 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002877 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002878 {
2879 // Option currently returns no systems. TBD
2880 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2881 systemName);
2882 return;
2883 }
2884 std::string resetType;
2885 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2886 {
2887 return;
2888 }
2889
2890 // Get the command and host vs. chassis
2891 std::string command;
2892 bool hostCommand = true;
2893 if ((resetType == "On") || (resetType == "ForceOn"))
2894 {
2895 command = "xyz.openbmc_project.State.Host.Transition.On";
2896 hostCommand = true;
2897 }
2898 else if (resetType == "ForceOff")
2899 {
2900 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2901 hostCommand = false;
2902 }
2903 else if (resetType == "ForceRestart")
2904 {
2905 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2906 hostCommand = true;
2907 }
2908 else if (resetType == "GracefulShutdown")
2909 {
2910 command = "xyz.openbmc_project.State.Host.Transition.Off";
2911 hostCommand = true;
2912 }
2913 else if (resetType == "GracefulRestart")
2914 {
2915 command =
2916 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2917 hostCommand = true;
2918 }
2919 else if (resetType == "PowerCycle")
2920 {
2921 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2922 hostCommand = true;
2923 }
2924 else if (resetType == "Nmi")
2925 {
2926 doNMI(asyncResp);
2927 return;
2928 }
2929 else
2930 {
2931 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2932 return;
2933 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002934 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002935
2936 if (hostCommand)
2937 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302938 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002939 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302940 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002941 }
2942 else
2943 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302944 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08002945 statePath / "chassis0",
2946 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302947 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002948 }
2949}
2950
Ed Tanousc1e219d2023-06-07 10:34:33 -07002951inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002952 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002953 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2954 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002955{
2956 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2957 {
2958 return;
2959 }
2960
2961 asyncResp->res.addHeader(
2962 boost::beast::http::field::link,
2963 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2964}
2965
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002966inline void afterPortRequest(
2967 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2968 const boost::system::error_code& ec,
2969 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2970{
2971 if (ec)
2972 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002973 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002974 messages::internalError(asyncResp->res);
2975 return;
2976 }
2977 for (const auto& data : socketData)
2978 {
2979 const std::string& socketPath = get<0>(data);
2980 const std::string& protocolName = get<1>(data);
2981 bool isProtocolEnabled = get<2>(data);
2982 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2983 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2984 // need to retrieve port number for
2985 // obmc-console-ssh service
2986 if (protocolName == "SSH")
2987 {
2988 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002989 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002990 int portNumber) {
2991 if (ec1)
2992 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002993 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002994 messages::internalError(asyncResp->res);
2995 return;
2996 }
2997 nlohmann::json& dataJson1 =
2998 asyncResp->res.jsonValue["SerialConsole"];
2999 dataJson1[protocolName]["Port"] = portNumber;
3000 });
3001 }
3002 }
3003}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003004
Patrick Williams504af5a2025-02-03 14:29:03 -05003005inline void handleComputerSystemGet(
3006 crow::App& app, const crow::Request& req,
3007 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3008 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003009{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003010 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3011 {
3012 return;
3013 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003014
Ed Tanous25b54db2024-04-17 15:40:31 -07003015 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003016 {
3017 // Option currently returns no systems. TBD
3018 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3019 systemName);
3020 return;
3021 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003022
Gunnar Mills68896202024-08-21 11:34:20 -05003023 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003024 {
Gunnar Mills68896202024-08-21 11:34:20 -05003025 if (systemName == "hypervisor")
3026 {
3027 handleHypervisorSystemGet(asyncResp);
3028 return;
3029 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003030 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003031
Ed Tanous253f11b2024-05-16 09:38:31 -07003032 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003033 {
3034 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3035 systemName);
3036 return;
3037 }
3038 asyncResp->res.addHeader(
3039 boost::beast::http::field::link,
3040 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3041 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003042 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003043 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3044 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanous539d8c62024-06-19 14:38:27 -07003045 asyncResp->res.jsonValue["SystemType"] =
3046 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003047 asyncResp->res.jsonValue["Description"] = "Computer System";
3048 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003049 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003050 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003051 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3052 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003053
Ed Tanous253f11b2024-05-16 09:38:31 -07003054 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3055 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3056 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3057 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3058 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3059 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003060 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003061 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3062 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003063
Ed Tanousc1e219d2023-06-07 10:34:33 -07003064 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003065 boost::urls::format(
3066 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3067 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003068 asyncResp->res
3069 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003070 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3071 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003072
Ed Tanous253f11b2024-05-16 09:38:31 -07003073 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3074 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3075 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3076 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003077
Ed Tanousc1e219d2023-06-07 10:34:33 -07003078 nlohmann::json::array_t managedBy;
3079 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003080 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3081 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003082 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003083 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3084 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003085
Ed Tanousc1e219d2023-06-07 10:34:33 -07003086 // Fill in SerialConsole info
3087 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3088 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003089
Ed Tanousc1e219d2023-06-07 10:34:33 -07003090 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3091 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3092 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3093 "Press ~. to exit console";
3094 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3095 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003096
Ed Tanous25b54db2024-04-17 15:40:31 -07003097 if constexpr (BMCWEB_KVM)
3098 {
3099 // Fill in GraphicalConsole info
3100 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3101 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3102 4;
3103 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3104 nlohmann::json::array_t({"KVMIP"});
3105 }
James Feistb49ac872019-05-21 15:12:01 -07003106
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003107 getMainChassisId(
3108 asyncResp, [](const std::string& chassisId,
3109 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3110 nlohmann::json::array_t chassisArray;
3111 nlohmann::json& chassis = chassisArray.emplace_back();
3112 chassis["@odata.id"] =
3113 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3114 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3115 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003116
George Liu59a17e42022-10-08 09:27:47 +08003117 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003118 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3119 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003120 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003121 getHostState(asyncResp);
3122 getBootProperties(asyncResp);
3123 getBootProgress(asyncResp);
3124 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003125 pcie_util::getPCIeDeviceList(asyncResp,
3126 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003127 getHostWatchdogTimer(asyncResp);
3128 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003129 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003130 getAutomaticRetryPolicy(asyncResp);
3131 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003132 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3133 {
3134 getProvisioningStatus(asyncResp);
3135 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003136 getTrustedModuleRequiredToBoot(asyncResp);
3137 getPowerMode(asyncResp);
3138 getIdlePowerSaver(asyncResp);
3139}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003140
Ed Tanousc1e219d2023-06-07 10:34:33 -07003141inline void handleComputerSystemPatch(
3142 crow::App& app, const crow::Request& req,
3143 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3144 const std::string& systemName)
3145{
3146 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3147 {
3148 return;
3149 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003150 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003151 {
3152 // Option currently returns no systems. TBD
3153 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3154 systemName);
3155 return;
3156 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003157 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003158 {
3159 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3160 systemName);
3161 return;
3162 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003163
Ed Tanousc1e219d2023-06-07 10:34:33 -07003164 asyncResp->res.addHeader(
3165 boost::beast::http::field::link,
3166 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003167
Ed Tanousc1e219d2023-06-07 10:34:33 -07003168 std::optional<bool> locationIndicatorActive;
3169 std::optional<std::string> indicatorLed;
3170 std::optional<std::string> assetTag;
3171 std::optional<std::string> powerRestorePolicy;
3172 std::optional<std::string> powerMode;
3173 std::optional<bool> wdtEnable;
3174 std::optional<std::string> wdtTimeOutAction;
3175 std::optional<std::string> bootSource;
3176 std::optional<std::string> bootType;
3177 std::optional<std::string> bootEnable;
3178 std::optional<std::string> bootAutomaticRetry;
3179 std::optional<uint32_t> bootAutomaticRetryAttempts;
3180 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003181 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003182 std::optional<bool> ipsEnable;
3183 std::optional<uint8_t> ipsEnterUtil;
3184 std::optional<uint64_t> ipsEnterTime;
3185 std::optional<uint8_t> ipsExitUtil;
3186 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003187
Patrick Williams504af5a2025-02-03 14:29:03 -05003188 if (!json_util::readJsonPatch( //
3189 req, asyncResp->res, //
3190 "AssetTag", assetTag, //
3191 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts, //
3192 "Boot/AutomaticRetryConfig", bootAutomaticRetry, //
3193 "Boot/BootSourceOverrideEnabled", bootEnable, //
3194 "Boot/BootSourceOverrideMode", bootType, //
3195 "Boot/BootSourceOverrideTarget", bootSource, //
3196 "Boot/StopBootOnFault", stopBootOnFault, //
Myung Baeafc474a2024-10-09 00:53:29 -07003197 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired, //
Patrick Williams504af5a2025-02-03 14:29:03 -05003198 "HostWatchdogTimer/FunctionEnabled", wdtEnable, //
3199 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction, //
3200 "IdlePowerSaver/Enabled", ipsEnable, //
3201 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime, //
3202 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil, //
3203 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime, //
3204 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil, //
3205 "IndicatorLED", indicatorLed, //
3206 "LocationIndicatorActive", locationIndicatorActive, //
3207 "PowerMode", powerMode, //
3208 "PowerRestorePolicy", powerRestorePolicy //
Myung Baeafc474a2024-10-09 00:53:29 -07003209 ))
Ed Tanousab344222024-08-07 18:01:23 -07003210 {
3211 return;
3212 }
James Feistb49ac872019-05-21 15:12:01 -07003213
Ed Tanousc1e219d2023-06-07 10:34:33 -07003214 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003215
Ed Tanousc1e219d2023-06-07 10:34:33 -07003216 if (assetTag)
3217 {
3218 setAssetTag(asyncResp, *assetTag);
3219 }
James Feistb49ac872019-05-21 15:12:01 -07003220
Ed Tanousc1e219d2023-06-07 10:34:33 -07003221 if (wdtEnable || wdtTimeOutAction)
3222 {
3223 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3224 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003225
Ed Tanousc1e219d2023-06-07 10:34:33 -07003226 if (bootSource || bootType || bootEnable)
3227 {
3228 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3229 }
3230 if (bootAutomaticRetry)
3231 {
3232 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3233 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003234
Ed Tanousc1e219d2023-06-07 10:34:33 -07003235 if (bootAutomaticRetryAttempts)
3236 {
3237 setAutomaticRetryAttempts(asyncResp,
3238 bootAutomaticRetryAttempts.value());
3239 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003240
Ed Tanousc1e219d2023-06-07 10:34:33 -07003241 if (bootTrustedModuleRequired)
3242 {
3243 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3244 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003245
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003246 if (stopBootOnFault)
3247 {
3248 setStopBootOnFault(asyncResp, *stopBootOnFault);
3249 }
3250
Ed Tanousc1e219d2023-06-07 10:34:33 -07003251 if (locationIndicatorActive)
3252 {
George Liu59a17e42022-10-08 09:27:47 +08003253 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003254 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003255
Ed Tanousc1e219d2023-06-07 10:34:33 -07003256 // TODO (Gunnar): Remove IndicatorLED after enough time has
3257 // passed
3258 if (indicatorLed)
3259 {
3260 setIndicatorLedState(asyncResp, *indicatorLed);
3261 asyncResp->res.addHeader(boost::beast::http::field::warning,
3262 "299 - \"IndicatorLED is deprecated. Use "
3263 "LocationIndicatorActive instead.\"");
3264 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003265
Ed Tanousc1e219d2023-06-07 10:34:33 -07003266 if (powerRestorePolicy)
3267 {
3268 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3269 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003270
Ed Tanousc1e219d2023-06-07 10:34:33 -07003271 if (powerMode)
3272 {
3273 setPowerMode(asyncResp, *powerMode);
3274 }
Chris Cain37bbf982021-09-20 10:53:09 -05003275
Ed Tanousc1e219d2023-06-07 10:34:33 -07003276 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3277 {
3278 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3279 ipsExitUtil, ipsExitTime);
3280 }
3281}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303282
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003283inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003284 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003285 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003286 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003287{
3288 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3289 {
3290 return;
3291 }
3292 asyncResp->res.addHeader(
3293 boost::beast::http::field::link,
3294 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3295}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003296
3297/**
3298 * @brief Translates allowed host transitions to redfish string
3299 *
3300 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3301 * @param[out] allowableValues The translated host transition(s)
3302 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303303 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003304 * allowableValues. If translation not possible, does nothing to
3305 * allowableValues.
3306 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003307inline void dbusToRfAllowedHostTransitions(
3308 const std::string& dbusAllowedHostTran,
3309 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003310{
3311 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3312 {
3313 allowableValues.emplace_back(resource::ResetType::On);
3314 allowableValues.emplace_back(resource::ResetType::ForceOn);
3315 }
3316 else if (dbusAllowedHostTran ==
3317 "xyz.openbmc_project.State.Host.Transition.Off")
3318 {
3319 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3320 }
3321 else if (dbusAllowedHostTran ==
3322 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3323 {
3324 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3325 }
3326 else if (dbusAllowedHostTran ==
3327 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3328 {
3329 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3330 }
3331 else
3332 {
3333 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3334 }
3335}
3336
3337inline void afterGetAllowedHostTransitions(
3338 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3339 const boost::system::error_code& ec,
3340 const std::vector<std::string>& allowedHostTransitions)
3341{
3342 nlohmann::json::array_t allowableValues;
3343
3344 // Supported on all systems currently
3345 allowableValues.emplace_back(resource::ResetType::ForceOff);
3346 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3347 allowableValues.emplace_back(resource::ResetType::Nmi);
3348
3349 if (ec)
3350 {
Ed Tanouse715d142024-03-07 15:47:37 -08003351 if ((ec.value() ==
3352 boost::system::linux_error::bad_request_descriptor) ||
3353 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003354 {
3355 // Property not implemented so just return defaults
3356 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3357 allowableValues.emplace_back(resource::ResetType::On);
3358 allowableValues.emplace_back(resource::ResetType::ForceOn);
3359 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3360 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3361 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3362 }
3363 else
3364 {
3365 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3366 messages::internalError(asyncResp->res);
3367 return;
3368 }
3369 }
3370 else
3371 {
3372 for (const std::string& transition : allowedHostTransitions)
3373 {
3374 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3375 dbusToRfAllowedHostTransitions(transition, allowableValues);
3376 }
3377 }
3378
3379 nlohmann::json::object_t parameter;
3380 parameter["Name"] = "ResetType";
3381 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003382 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003383 parameter["AllowableValues"] = std::move(allowableValues);
3384 nlohmann::json::array_t parameters;
3385 parameters.emplace_back(std::move(parameter));
3386 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3387}
3388
Ed Tanousc1e219d2023-06-07 10:34:33 -07003389inline void handleSystemCollectionResetActionGet(
3390 crow::App& app, const crow::Request& req,
3391 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3392 const std::string& systemName)
3393{
3394 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3395 {
3396 return;
3397 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003398 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003399 {
3400 // Option currently returns no systems. TBD
3401 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3402 systemName);
3403 return;
3404 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003405
Gunnar Mills68896202024-08-21 11:34:20 -05003406 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003407 {
Gunnar Mills68896202024-08-21 11:34:20 -05003408 if (systemName == "hypervisor")
3409 {
3410 handleHypervisorResetActionGet(asyncResp);
3411 return;
3412 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003413 }
3414
Ed Tanous253f11b2024-05-16 09:38:31 -07003415 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003416 {
3417 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3418 systemName);
3419 return;
3420 }
3421
3422 asyncResp->res.addHeader(
3423 boost::beast::http::field::link,
3424 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3425
3426 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003427 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3428 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003429 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3430 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3431 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3432
Andrew Geissler33e1f122024-02-26 21:10:16 -06003433 // Look to see if system defines AllowedHostTransitions
Ed Tanousdeae6a72024-11-11 21:58:57 -08003434 dbus::utility::getProperty<std::vector<std::string>>(
3435 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
3436 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
Andrew Geissler33e1f122024-02-26 21:10:16 -06003437 [asyncResp](const boost::system::error_code& ec,
3438 const std::vector<std::string>& allowedHostTransitions) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003439 afterGetAllowedHostTransitions(asyncResp, ec,
3440 allowedHostTransitions);
3441 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003442}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303443/**
3444 * SystemResetActionInfo derived class for delivering Computer Systems
3445 * ResetType AllowableValues using ResetInfo schema.
3446 */
Ed Tanous100afe52023-06-07 13:30:46 -07003447inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303448{
Ed Tanous100afe52023-06-07 13:30:46 -07003449 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3450 .privileges(redfish::privileges::headComputerSystemCollection)
3451 .methods(boost::beast::http::verb::head)(
3452 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3453
3454 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3455 .privileges(redfish::privileges::getComputerSystemCollection)
3456 .methods(boost::beast::http::verb::get)(
3457 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3458
3459 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3460 .privileges(redfish::privileges::headComputerSystem)
3461 .methods(boost::beast::http::verb::head)(
3462 std::bind_front(handleComputerSystemHead, std::ref(app)));
3463
3464 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3465 .privileges(redfish::privileges::getComputerSystem)
3466 .methods(boost::beast::http::verb::get)(
3467 std::bind_front(handleComputerSystemGet, std::ref(app)));
3468
3469 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3470 .privileges(redfish::privileges::patchComputerSystem)
3471 .methods(boost::beast::http::verb::patch)(
3472 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3473
3474 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3475 .privileges(redfish::privileges::postComputerSystem)
3476 .methods(boost::beast::http::verb::post)(std::bind_front(
3477 handleComputerSystemResetActionPost, std::ref(app)));
3478
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003479 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003480 .privileges(redfish::privileges::headActionInfo)
3481 .methods(boost::beast::http::verb::head)(std::bind_front(
3482 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003483 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003484 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003485 .methods(boost::beast::http::verb::get)(std::bind_front(
3486 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003487}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003488} // namespace redfish