blob: e4f02cc739c362711441e6543ce65c81e8200c51 [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 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400999 if (ec.value() == boost::asio::error::host_unreachable)
1000 {
1001 return;
1002 }
1003 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1004 messages::internalError(asyncResp->res);
Nan Zhou5ef735c2022-06-22 05:24:21 +00001005 return;
1006 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301007
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001008 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301009
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001010 auto rfSource = dbusToRfBootSource(bootSourceStr);
1011 if (!rfSource.empty())
1012 {
1013 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1014 rfSource;
1015 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001016
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001017 // Get BootMode as BootSourceOverrideTarget is constructed
1018 // from both BootSource and BootMode
1019 getBootOverrideMode(asyncResp);
1020 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301021}
1022
1023/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001024 * @brief This functions abstracts all the logic behind getting a
1025 * "BootSourceOverrideEnabled" property from an overall boot override enable
1026 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301027 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001028 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029 *
1030 * @return None.
1031 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301032
Ed Tanousac106bf2023-06-07 09:24:59 -07001033inline void processBootOverrideEnable(
1034 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1035 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001036{
1037 if (!bootOverrideEnableSetting)
1038 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001039 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1040 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001041 return;
1042 }
1043
1044 // If boot source override is enabled, we need to check 'one_time'
1045 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001046 dbus::utility::getProperty<bool>(
1047 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001048 "/xyz/openbmc_project/control/host0/boot/one_time",
1049 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001050 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001051 if (ec)
1052 {
1053 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1054 messages::internalError(asyncResp->res);
1055 return;
1056 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301057
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001058 if (oneTimeSetting)
1059 {
1060 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1061 "Once";
1062 }
1063 else
1064 {
1065 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1066 "Continuous";
1067 }
1068 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301069}
1070
1071/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001072 * @brief Retrieves boot override enable over DBUS
1073 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001074 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001075 *
1076 * @return None.
1077 */
1078
Patrick Williams504af5a2025-02-03 14:29:03 -05001079inline void getBootOverrideEnable(
1080 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001081{
Ed Tanousdeae6a72024-11-11 21:58:57 -08001082 dbus::utility::getProperty<bool>(
1083 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001084 "/xyz/openbmc_project/control/host0/boot",
1085 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001086 [asyncResp](const boost::system::error_code& ec,
1087 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001088 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001089 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001090 if (ec.value() == boost::asio::error::host_unreachable)
1091 {
1092 return;
1093 }
1094 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1095 messages::internalError(asyncResp->res);
Nan Zhou5ef735c2022-06-22 05:24:21 +00001096 return;
1097 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001098
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001099 processBootOverrideEnable(asyncResp, bootOverrideEnable);
1100 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001101}
1102
1103/**
1104 * @brief Retrieves boot source override properties
1105 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001106 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001107 *
1108 * @return None.
1109 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001110inline void getBootProperties(
1111 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001112{
Ed Tanous62598e32023-07-17 17:06:25 -07001113 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001114
Ed Tanousac106bf2023-06-07 09:24:59 -07001115 getBootOverrideSource(asyncResp);
1116 getBootOverrideType(asyncResp);
1117 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001118}
1119
1120/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001121 * @brief Retrieves the Last Reset Time
1122 *
1123 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1124 * and power off. Even though this is the "system" Redfish object look at the
1125 * chassis D-Bus interface for the LastStateChangeTime since this has the
1126 * last power operation time.
1127 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001128 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001129 *
1130 * @return None.
1131 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001132inline void getLastResetTime(
1133 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001134{
Ed Tanous62598e32023-07-17 17:06:25 -07001135 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001136
Ed Tanousdeae6a72024-11-11 21:58:57 -08001137 dbus::utility::getProperty<uint64_t>(
1138 "xyz.openbmc_project.State.Chassis",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001139 "/xyz/openbmc_project/state/chassis0",
1140 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001141 [asyncResp](const boost::system::error_code& ec,
1142 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001143 if (ec)
1144 {
1145 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1146 return;
1147 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001148
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001149 // LastStateChangeTime is epoch time, in milliseconds
1150 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1151 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001152
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001153 // Convert to ISO 8601 standard
1154 asyncResp->res.jsonValue["LastResetTime"] =
1155 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1156 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001157}
1158
1159/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001160 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1161 *
1162 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1163 * corresponding property "AttemptsLeft" that keeps track of the amount of
1164 * automatic retry attempts left are hosted in phosphor-state-manager through
1165 * dbus.
1166 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001167 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001168 *
1169 * @return None.
1170 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001171inline void getAutomaticRebootAttempts(
1172 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001173{
Ed Tanous62598e32023-07-17 17:06:25 -07001174 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001175
Ed Tanousdeae6a72024-11-11 21:58:57 -08001176 dbus::utility::getAllProperties(
1177 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Corey Hardesty797d5da2022-04-26 17:54:52 +08001178 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001179 [asyncResp{asyncResp}](
1180 const boost::system::error_code& ec,
1181 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001182 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001183 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301184 if (ec.value() != EBADR &&
1185 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001186 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301187 // Service not available, no error, just don't return
1188 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001189 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1190 messages::internalError(asyncResp->res);
1191 }
1192 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001193 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001194
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001195 const uint32_t* attemptsLeft = nullptr;
1196 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001197
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001198 const bool success = sdbusplus::unpackPropertiesNoThrow(
1199 dbus_utils::UnpackErrorPrinter(), propertiesList,
1200 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001201
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001202 if (!success)
1203 {
1204 messages::internalError(asyncResp->res);
1205 return;
1206 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001207
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001208 if (attemptsLeft != nullptr)
1209 {
1210 asyncResp->res
1211 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1212 *attemptsLeft;
1213 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001214
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001215 if (retryAttempts != nullptr)
1216 {
1217 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1218 *retryAttempts;
1219 }
1220 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001221}
1222
1223/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001224 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1225 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001226 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001227 *
1228 * @return None.
1229 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001230inline void getAutomaticRetryPolicy(
1231 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001232{
Ed Tanous62598e32023-07-17 17:06:25 -07001233 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001234
Ed Tanousdeae6a72024-11-11 21:58:57 -08001235 dbus::utility::getProperty<bool>(
1236 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001237 "/xyz/openbmc_project/control/host0/auto_reboot",
1238 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001239 [asyncResp](const boost::system::error_code& ec,
1240 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001241 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001242 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301243 // Service not available, no error, just don't return
1244 // AutoReboot information
1245 if (ec.value() != EBADR &&
1246 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001247 {
1248 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1249 messages::internalError(asyncResp->res);
1250 }
1251 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001252 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001253
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001254 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1255 if (autoRebootEnabled)
1256 {
1257 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1258 "RetryAttempts";
1259 }
1260 else
1261 {
1262 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1263 "Disabled";
1264 }
1265 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001266
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001267 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1268 // and RetryAttempts. OpenBMC only supports Disabled and
1269 // RetryAttempts.
1270 nlohmann::json::array_t allowed;
1271 allowed.emplace_back("Disabled");
1272 allowed.emplace_back("RetryAttempts");
1273 asyncResp->res
1274 .jsonValue["Boot"]
1275 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1276 std::move(allowed);
1277 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001278}
1279
1280/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001281 * @brief Sets RetryAttempts
1282 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001283 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001284 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1285 *
1286 *@return None.
1287 */
1288
Ed Tanousac106bf2023-06-07 09:24:59 -07001289inline void setAutomaticRetryAttempts(
1290 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1291 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001292{
Ed Tanous62598e32023-07-17 17:06:25 -07001293 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001294 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301295 asyncResp, "Boot/AutomaticRetryAttempts",
1296 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001297 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001298 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301299 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001300}
1301
Ed Tanous8d69c662023-06-21 10:29:06 -07001302inline computer_system::PowerRestorePolicyTypes
1303 redfishPowerRestorePolicyFromDbus(std::string_view value)
1304{
1305 if (value ==
1306 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1307 {
1308 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1309 }
1310 if (value ==
1311 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1312 {
1313 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1314 }
1315 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001316 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001317 {
1318 return computer_system::PowerRestorePolicyTypes::LastState;
1319 }
1320 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1321 {
1322 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1323 }
1324 return computer_system::PowerRestorePolicyTypes::Invalid;
1325}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001326/**
George Liuc6a620f2020-04-10 17:18:11 +08001327 * @brief Retrieves power restore policy over DBUS.
1328 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001329 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001330 *
1331 * @return None.
1332 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001333inline void getPowerRestorePolicy(
1334 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001335{
Ed Tanous62598e32023-07-17 17:06:25 -07001336 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001337
Ed Tanousdeae6a72024-11-11 21:58:57 -08001338 dbus::utility::getProperty<std::string>(
1339 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001340 "/xyz/openbmc_project/control/host0/power_restore_policy",
1341 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001342 [asyncResp](const boost::system::error_code& ec,
1343 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001344 if (ec)
1345 {
1346 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1347 return;
1348 }
1349 computer_system::PowerRestorePolicyTypes restore =
1350 redfishPowerRestorePolicyFromDbus(policy);
1351 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1352 {
1353 messages::internalError(asyncResp->res);
1354 return;
1355 }
George Liuc6a620f2020-04-10 17:18:11 +08001356
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001357 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1358 });
George Liuc6a620f2020-04-10 17:18:11 +08001359}
1360
1361/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001362 * @brief Stop Boot On Fault over DBUS.
1363 *
1364 * @param[in] asyncResp Shared pointer for generating response message.
1365 *
1366 * @return None.
1367 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001368inline void getStopBootOnFault(
1369 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001370{
Ed Tanous62598e32023-07-17 17:06:25 -07001371 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001372
Ed Tanousdeae6a72024-11-11 21:58:57 -08001373 dbus::utility::getProperty<bool>(
1374 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001375 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1376 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001377 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001378 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301379 // Service not available, no error, just don't return
1380 // StopBootOnFault information
1381 if (ec.value() != EBADR ||
1382 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001383 {
1384 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1385 messages::internalError(asyncResp->res);
1386 }
1387 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001388 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001389
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001390 if (value)
1391 {
1392 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1393 computer_system::StopBootOnFault::AnyFault;
1394 }
1395 else
1396 {
1397 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1398 computer_system::StopBootOnFault::Never;
1399 }
1400 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001401}
1402
1403/**
Ali Ahmed19817712021-06-29 17:01:52 -05001404 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1405 * TPM is required for booting the host.
1406 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001407 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001408 *
1409 * @return None.
1410 */
1411inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001412 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001413{
Ed Tanous62598e32023-07-17 17:06:25 -07001414 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001415 constexpr std::array<std::string_view, 1> interfaces = {
1416 "xyz.openbmc_project.Control.TPM.Policy"};
1417 dbus::utility::getSubTree(
1418 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001419 [asyncResp](const boost::system::error_code& ec,
1420 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001421 if (ec)
Ali Ahmed19817712021-06-29 17:01:52 -05001422 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001423 BMCWEB_LOG_DEBUG(
1424 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1425 // This is an optional D-Bus object so just return if
1426 // error occurs
1427 return;
1428 }
1429 if (subtree.empty())
1430 {
1431 // As noted above, this is an optional interface so just return
1432 // if there is no instance found
1433 return;
1434 }
1435
1436 /* When there is more than one TPMEnable object... */
1437 if (subtree.size() > 1)
1438 {
1439 BMCWEB_LOG_DEBUG(
1440 "DBUS response has more than 1 TPM Enable object:{}",
1441 subtree.size());
1442 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001443 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001444 return;
1445 }
1446
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001447 // Make sure the Dbus response map has a service and objectPath
1448 // field
1449 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
Ali Ahmed19817712021-06-29 17:01:52 -05001450 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001451 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1452 messages::internalError(asyncResp->res);
1453 return;
Ali Ahmed19817712021-06-29 17:01:52 -05001454 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001455
1456 const std::string& path = subtree[0].first;
1457 const std::string& serv = subtree[0].second.begin()->first;
1458
1459 // Valid TPM Enable object found, now reading the current value
Ed Tanousdeae6a72024-11-11 21:58:57 -08001460 dbus::utility::getProperty<bool>(
1461 serv, path, "xyz.openbmc_project.Control.TPM.Policy",
1462 "TPMEnable",
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001463 [asyncResp](const boost::system::error_code& ec2,
1464 bool tpmRequired) {
1465 if (ec2)
1466 {
1467 BMCWEB_LOG_ERROR(
1468 "D-BUS response error on TPM.Policy Get{}", ec2);
1469 messages::internalError(asyncResp->res);
1470 return;
1471 }
1472
1473 if (tpmRequired)
1474 {
1475 asyncResp->res
1476 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1477 "Required";
1478 }
1479 else
1480 {
1481 asyncResp->res
1482 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1483 "Disabled";
1484 }
1485 });
George Liue99073f2022-12-09 11:06:16 +08001486 });
Ali Ahmed19817712021-06-29 17:01:52 -05001487}
1488
1489/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001490 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1491 * TPM is required for booting the host.
1492 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001493 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001494 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1495 *
1496 * @return None.
1497 */
1498inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001499 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001500{
Ed Tanous62598e32023-07-17 17:06:25 -07001501 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001502 constexpr std::array<std::string_view, 1> interfaces = {
1503 "xyz.openbmc_project.Control.TPM.Policy"};
1504 dbus::utility::getSubTree(
1505 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001506 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001507 tpmRequired](const boost::system::error_code& ec,
1508 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001509 if (ec)
1510 {
1511 BMCWEB_LOG_ERROR(
1512 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1513 messages::internalError(asyncResp->res);
1514 return;
1515 }
1516 if (subtree.empty())
1517 {
1518 messages::propertyValueNotInList(asyncResp->res,
1519 "ComputerSystem",
1520 "TrustedModuleRequiredToBoot");
1521 return;
1522 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001523
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001524 /* When there is more than one TPMEnable object... */
1525 if (subtree.size() > 1)
1526 {
1527 BMCWEB_LOG_DEBUG(
1528 "DBUS response has more than 1 TPM Enable object:{}",
1529 subtree.size());
1530 // Throw an internal Error and return
1531 messages::internalError(asyncResp->res);
1532 return;
1533 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001534
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001535 // Make sure the Dbus response map has a service and objectPath
1536 // field
1537 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1538 {
1539 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1540 messages::internalError(asyncResp->res);
1541 return;
1542 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001543
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001544 const std::string& path = subtree[0].first;
1545 const std::string& serv = subtree[0].second.begin()->first;
Ed Tanous002d39b2022-05-31 08:59:27 -07001546
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001547 if (serv.empty())
1548 {
1549 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1550 messages::internalError(asyncResp->res);
1551 return;
1552 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001553
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001554 // Valid TPM Enable object found, now setting the value
1555 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1556 path, "xyz.openbmc_project.Control.TPM.Policy",
1557 "TPMEnable", tpmRequired);
1558 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001559}
1560
1561/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301562 * @brief Sets boot properties into DBUS object(s).
1563 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001564 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001565 * @param[in] bootType The boot type to set.
1566 * @return Integer error code.
1567 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001568inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001569 const std::optional<std::string>& bootType)
1570{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001571 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001572
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001573 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001574 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001575 return;
1576 }
1577
1578 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001579 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001580 // Figure out which DBUS interface and property to use
1581 if (*bootType == "Legacy")
1582 {
1583 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1584 }
1585 else if (*bootType == "UEFI")
1586 {
1587 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1588 }
1589 else
1590 {
Ed Tanous62598e32023-07-17 17:06:25 -07001591 BMCWEB_LOG_DEBUG("Invalid property value for "
1592 "BootSourceOverrideMode: {}",
1593 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001594 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001595 "BootSourceOverrideMode");
1596 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001597 }
1598
1599 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001600 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001601
Ginu Georgee93abac2024-06-14 17:35:27 +05301602 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1603 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001604 sdbusplus::message::object_path(
1605 "/xyz/openbmc_project/control/host0/boot"),
1606 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301607 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001608}
1609
1610/**
1611 * @brief Sets boot properties into DBUS object(s).
1612 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001613 * @param[in] asyncResp Shared pointer for generating response
1614 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001615 * @param[in] bootType The boot type to set.
1616 * @return Integer error code.
1617 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001618inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001619 const std::optional<std::string>& bootEnable)
1620{
1621 if (!bootEnable)
1622 {
1623 return;
1624 }
1625 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001626 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001627
1628 bool bootOverrideEnable = false;
1629 bool bootOverridePersistent = false;
1630 // Figure out which DBUS interface and property to use
1631 if (*bootEnable == "Disabled")
1632 {
1633 bootOverrideEnable = false;
1634 }
1635 else if (*bootEnable == "Once")
1636 {
1637 bootOverrideEnable = true;
1638 bootOverridePersistent = false;
1639 }
1640 else if (*bootEnable == "Continuous")
1641 {
1642 bootOverrideEnable = true;
1643 bootOverridePersistent = true;
1644 }
1645 else
1646 {
Ed Tanous62598e32023-07-17 17:06:25 -07001647 BMCWEB_LOG_DEBUG(
1648 "Invalid property value for BootSourceOverrideEnabled: {}",
1649 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001650 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001651 "BootSourceOverrideEnabled");
1652 return;
1653 }
1654
1655 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001656 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001657
Ginu Georgee93abac2024-06-14 17:35:27 +05301658 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1659 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001660 sdbusplus::message::object_path(
1661 "/xyz/openbmc_project/control/host0/boot"),
1662 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301663 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001664
1665 if (!bootOverrideEnable)
1666 {
1667 return;
1668 }
1669
1670 // In case boot override is enabled we need to set correct value for the
1671 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001672 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1673 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001674
Ginu Georgee93abac2024-06-14 17:35:27 +05301675 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1676 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001677 sdbusplus::message::object_path(
1678 "/xyz/openbmc_project/control/host0/boot/one_time"),
1679 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301680 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001681}
1682
1683/**
1684 * @brief Sets boot properties into DBUS object(s).
1685 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001686 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301687 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301688 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001689 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301690 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001691inline void setBootModeOrSource(
1692 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1693 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301694{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001695 std::string bootSourceStr;
1696 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001697
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001698 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301699 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001700 return;
1701 }
1702
1703 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001704 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001705 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001706 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1707 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001708 {
Ed Tanous62598e32023-07-17 17:06:25 -07001709 BMCWEB_LOG_DEBUG(
1710 "Invalid property value for BootSourceOverrideTarget: {}",
1711 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001712 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001713 "BootSourceTargetOverride");
1714 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001715 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301716
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001717 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001718 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1719 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001720
Ginu Georgee93abac2024-06-14 17:35:27 +05301721 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1722 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001723 sdbusplus::message::object_path(
1724 "/xyz/openbmc_project/control/host0/boot"),
1725 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301726 bootSourceStr);
1727 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1728 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001729 sdbusplus::message::object_path(
1730 "/xyz/openbmc_project/control/host0/boot"),
1731 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301732 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001733}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001734
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001735/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001736 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301737 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001738 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301739 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001740 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301741 * @param[in] bootEnable The boot override enable from incoming RF request.
1742 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001743 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301744 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001745
Patrick Williams504af5a2025-02-03 14:29:03 -05001746inline void setBootProperties(
1747 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1748 const std::optional<std::string>& bootSource,
1749 const std::optional<std::string>& bootType,
1750 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301751{
Ed Tanous62598e32023-07-17 17:06:25 -07001752 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301753
Ed Tanousac106bf2023-06-07 09:24:59 -07001754 setBootModeOrSource(asyncResp, bootSource);
1755 setBootType(asyncResp, bootType);
1756 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301757}
1758
George Liuc6a620f2020-04-10 17:18:11 +08001759/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001760 * @brief Sets AssetTag
1761 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001762 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001763 * @param[in] assetTag "AssetTag" from request.
1764 *
1765 * @return None.
1766 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001767inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001768 const std::string& assetTag)
1769{
George Liue99073f2022-12-09 11:06:16 +08001770 constexpr std::array<std::string_view, 1> interfaces = {
1771 "xyz.openbmc_project.Inventory.Item.System"};
1772 dbus::utility::getSubTree(
1773 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001774 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001775 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001776 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001777 if (ec)
1778 {
1779 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1780 messages::internalError(asyncResp->res);
1781 return;
1782 }
1783 if (subtree.empty())
1784 {
1785 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1786 messages::internalError(asyncResp->res);
1787 return;
1788 }
1789 // Assume only 1 system D-Bus object
1790 // Throw an error if there is more than 1
1791 if (subtree.size() > 1)
1792 {
1793 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1794 messages::internalError(asyncResp->res);
1795 return;
1796 }
1797 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1798 {
1799 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1800 messages::internalError(asyncResp->res);
1801 return;
1802 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001803
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001804 const std::string& path = subtree[0].first;
1805 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001806
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001807 if (service.empty())
1808 {
1809 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1810 messages::internalError(asyncResp->res);
1811 return;
1812 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001813
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001814 setDbusProperty(asyncResp, "AssetTag", service, path,
1815 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1816 "AssetTag", assetTag);
1817 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001818}
1819
1820/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001821 * @brief Validate the specified stopBootOnFault is valid and return the
1822 * stopBootOnFault name associated with that string
1823 *
1824 * @param[in] stopBootOnFaultString String representing the desired
1825 * stopBootOnFault
1826 *
1827 * @return stopBootOnFault value or empty if incoming value is not valid
1828 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001829inline std::optional<bool> validstopBootOnFault(
1830 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001831{
1832 if (stopBootOnFaultString == "AnyFault")
1833 {
1834 return true;
1835 }
1836
1837 if (stopBootOnFaultString == "Never")
1838 {
1839 return false;
1840 }
1841
1842 return std::nullopt;
1843}
1844
1845/**
1846 * @brief Sets stopBootOnFault
1847 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001848 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001849 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1850 *
1851 * @return None.
1852 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001853inline void setStopBootOnFault(
1854 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1855 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001856{
Ed Tanous62598e32023-07-17 17:06:25 -07001857 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001858
1859 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1860 if (!stopBootEnabled)
1861 {
Ed Tanous62598e32023-07-17 17:06:25 -07001862 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1863 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001864 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001865 "StopBootOnFault");
1866 return;
1867 }
1868
Ginu Georgee93abac2024-06-14 17:35:27 +05301869 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1870 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001871 sdbusplus::message::object_path(
1872 "/xyz/openbmc_project/logging/settings"),
1873 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301874 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001875}
1876
1877/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001878 * @brief Sets automaticRetry (Auto Reboot)
1879 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001880 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001881 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1882 *
1883 * @return None.
1884 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001885inline void setAutomaticRetry(
1886 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1887 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001888{
Ed Tanous62598e32023-07-17 17:06:25 -07001889 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001890
1891 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001892 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001893
1894 if (automaticRetryConfig == "Disabled")
1895 {
1896 autoRebootEnabled = false;
1897 }
1898 else if (automaticRetryConfig == "RetryAttempts")
1899 {
1900 autoRebootEnabled = true;
1901 }
1902 else
1903 {
Ed Tanous62598e32023-07-17 17:06:25 -07001904 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1905 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001906 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001907 "AutomaticRetryConfig");
1908 return;
1909 }
1910
Ginu Georgee93abac2024-06-14 17:35:27 +05301911 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1912 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001913 sdbusplus::message::object_path(
1914 "/xyz/openbmc_project/control/host0/auto_reboot"),
1915 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301916 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001917}
1918
Ed Tanous8d69c662023-06-21 10:29:06 -07001919inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1920{
1921 if (policy == "AlwaysOn")
1922 {
1923 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1924 }
1925 if (policy == "AlwaysOff")
1926 {
1927 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1928 }
1929 if (policy == "LastState")
1930 {
1931 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1932 }
1933 return "";
1934}
1935
Gunnar Mills69f35302020-05-17 16:06:31 -05001936/**
George Liuc6a620f2020-04-10 17:18:11 +08001937 * @brief Sets power restore policy properties.
1938 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001939 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001940 * @param[in] policy power restore policy properties from request.
1941 *
1942 * @return None.
1943 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001944inline void setPowerRestorePolicy(
1945 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1946 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001947{
Ed Tanous62598e32023-07-17 17:06:25 -07001948 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001949
Ed Tanous8d69c662023-06-21 10:29:06 -07001950 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001951
Ed Tanous8d69c662023-06-21 10:29:06 -07001952 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001953 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001954 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001955 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001956 return;
1957 }
1958
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001959 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301960 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001961 sdbusplus::message::object_path(
1962 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001963 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301964 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001965}
1966
AppaRao Pulia6349912019-10-18 17:16:08 +05301967/**
1968 * @brief Retrieves provisioning status
1969 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001970 * @param[in] asyncResp Shared pointer for completing asynchronous
1971 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301972 *
1973 * @return None.
1974 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001975inline void getProvisioningStatus(
1976 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301977{
Ed Tanous62598e32023-07-17 17:06:25 -07001978 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08001979 dbus::utility::getAllProperties(
1980 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1981 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001982 [asyncResp](const boost::system::error_code& ec,
1983 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001984 nlohmann::json& oemPFR =
1985 asyncResp->res
1986 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1987 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1988 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1989 oemPFR["@odata.type"] =
1990 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001991
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001992 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05301993 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001994 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1995 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07001996 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001997 FirmwareProvisioningStatus::NotProvisioned;
1998 return;
1999 }
2000
2001 const bool* provState = nullptr;
2002 const bool* lockState = nullptr;
2003
2004 const bool success = sdbusplus::unpackPropertiesNoThrow(
2005 dbus_utils::UnpackErrorPrinter(), propertiesList,
2006 "UfmProvisioned", provState, "UfmLocked", lockState);
2007
2008 if (!success)
2009 {
2010 messages::internalError(asyncResp->res);
2011 return;
2012 }
2013
2014 if ((provState == nullptr) || (lockState == nullptr))
2015 {
2016 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2017 messages::internalError(asyncResp->res);
2018 return;
2019 }
2020
2021 if (*provState)
2022 {
2023 if (*lockState)
2024 {
2025 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2026 FirmwareProvisioningStatus::ProvisionedAndLocked;
2027 }
2028 else
2029 {
2030 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2031 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2032 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302033 }
2034 else
2035 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002036 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002037 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302038 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002039 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302040}
AppaRao Pulia6349912019-10-18 17:16:08 +05302041
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302042/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002043 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002044 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002045 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002046 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002047 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002048 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002049inline computer_system::PowerMode translatePowerModeString(
2050 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002051{
Chris Cainb6655102024-02-01 14:35:33 -06002052 using PowerMode = computer_system::PowerMode;
2053
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002054 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002055 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002056 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002057 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002058 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002059 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002060 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002061 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002062 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002063 if (modeString ==
2064 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002065 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002066 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002067 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002068 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002069 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2070 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002071 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002072 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002073 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002074 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2075 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002076 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002077 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002078 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002079 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2080 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002081 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002082 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002083 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002084 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002085 return PowerMode::OEM;
2086 }
2087 // Any other values would be invalid
2088 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2089 return PowerMode::Invalid;
2090}
2091
Patrick Williams504af5a2025-02-03 14:29:03 -05002092inline void afterGetPowerMode(
2093 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2094 const boost::system::error_code& ec,
2095 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002096{
2097 if (ec)
2098 {
2099 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2100 messages::internalError(asyncResp->res);
2101 return;
2102 }
2103
2104 std::string powerMode;
2105 const std::vector<std::string>* allowedModes = nullptr;
2106 const bool success = sdbusplus::unpackPropertiesNoThrow(
2107 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2108 "AllowedPowerModes", allowedModes);
2109
2110 if (!success)
2111 {
2112 messages::internalError(asyncResp->res);
2113 return;
2114 }
2115
2116 nlohmann::json::array_t modeList;
2117 if (allowedModes == nullptr)
2118 {
2119 modeList.emplace_back("Static");
2120 modeList.emplace_back("MaximumPerformance");
2121 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002122 }
2123 else
2124 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002125 for (const auto& aMode : *allowedModes)
2126 {
2127 computer_system::PowerMode modeValue =
2128 translatePowerModeString(aMode);
2129 if (modeValue == computer_system::PowerMode::Invalid)
2130 {
2131 messages::internalError(asyncResp->res);
2132 continue;
2133 }
2134 modeList.emplace_back(modeValue);
2135 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002136 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002137 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002138
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002139 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2140 const computer_system::PowerMode modeValue =
2141 translatePowerModeString(powerMode);
2142 if (modeValue == computer_system::PowerMode::Invalid)
2143 {
2144 messages::internalError(asyncResp->res);
2145 return;
2146 }
2147 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2148}
Chris Cain3a2d04242021-05-28 16:57:10 -05002149/**
2150 * @brief Retrieves system power mode
2151 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002152 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002153 *
2154 * @return None.
2155 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002156inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002157{
Ed Tanous62598e32023-07-17 17:06:25 -07002158 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002159
2160 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002161 constexpr std::array<std::string_view, 1> interfaces = {
2162 "xyz.openbmc_project.Control.Power.Mode"};
2163 dbus::utility::getSubTree(
2164 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002165 [asyncResp](const boost::system::error_code& ec,
2166 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002167 if (ec)
2168 {
2169 BMCWEB_LOG_DEBUG(
2170 "DBUS response error on Power.Mode GetSubTree {}", ec);
2171 // This is an optional D-Bus object so just return if
2172 // error occurs
2173 return;
2174 }
2175 if (subtree.empty())
2176 {
2177 // As noted above, this is an optional interface so just return
2178 // if there is no instance found
2179 return;
2180 }
2181 if (subtree.size() > 1)
2182 {
2183 // More then one PowerMode object is not supported and is an
2184 // error
2185 BMCWEB_LOG_DEBUG(
2186 "Found more than 1 system D-Bus Power.Mode objects: {}",
2187 subtree.size());
2188 messages::internalError(asyncResp->res);
2189 return;
2190 }
2191 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2192 {
2193 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2194 messages::internalError(asyncResp->res);
2195 return;
2196 }
2197 const std::string& path = subtree[0].first;
2198 const std::string& service = subtree[0].second.begin()->first;
2199 if (service.empty())
2200 {
2201 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2202 messages::internalError(asyncResp->res);
2203 return;
2204 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002205
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002206 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002207 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002208 *crow::connections::systemBus, service, path,
2209 "xyz.openbmc_project.Control.Power.Mode",
2210 [asyncResp](
2211 const boost::system::error_code& ec2,
2212 const dbus::utility::DBusPropertiesMap& properties) {
2213 afterGetPowerMode(asyncResp, ec2, properties);
2214 });
George Liue99073f2022-12-09 11:06:16 +08002215 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002216}
2217
2218/**
2219 * @brief Validate the specified mode is valid and return the PowerMode
2220 * name associated with that string
2221 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002222 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002223 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002224 *
2225 * @return PowerMode value or empty string if mode is not valid
2226 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002227inline std::string validatePowerMode(
2228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2229 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002230{
Chris Cainb6655102024-02-01 14:35:33 -06002231 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002232 std::string mode;
2233
Chris Cainb6655102024-02-01 14:35:33 -06002234 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002235 {
2236 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2237 }
Chris Cainb6655102024-02-01 14:35:33 -06002238 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002239 {
George Liu0fda0f12021-11-16 10:06:17 +08002240 mode =
2241 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002242 }
Chris Cainb6655102024-02-01 14:35:33 -06002243 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002244 {
2245 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2246 }
Chris Cainb6655102024-02-01 14:35:33 -06002247 else if (modeValue == PowerMode::BalancedPerformance)
2248 {
2249 mode =
2250 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2251 }
2252 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2253 {
2254 mode =
2255 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2256 }
2257 else if (modeValue == PowerMode::EfficiencyFavorPower)
2258 {
2259 mode =
2260 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2261 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002262 else
2263 {
Chris Cainb6655102024-02-01 14:35:33 -06002264 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002265 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002266 }
2267 return mode;
2268}
2269
2270/**
2271 * @brief Sets system power mode.
2272 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002273 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002274 * @param[in] pmode System power mode from request.
2275 *
2276 * @return None.
2277 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002278inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002279 const std::string& pmode)
2280{
Ed Tanous62598e32023-07-17 17:06:25 -07002281 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002282
Ed Tanousac106bf2023-06-07 09:24:59 -07002283 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002284 if (powerMode.empty())
2285 {
2286 return;
2287 }
2288
2289 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002290 constexpr std::array<std::string_view, 1> interfaces = {
2291 "xyz.openbmc_project.Control.Power.Mode"};
2292 dbus::utility::getSubTree(
2293 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002294 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002295 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002296 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002297 if (ec)
2298 {
2299 BMCWEB_LOG_ERROR(
2300 "DBUS response error on Power.Mode GetSubTree {}", ec);
2301 // This is an optional D-Bus object, but user attempted to patch
2302 messages::internalError(asyncResp->res);
2303 return;
2304 }
2305 if (subtree.empty())
2306 {
2307 // This is an optional D-Bus object, but user attempted to patch
2308 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2309 "PowerMode");
2310 return;
2311 }
2312 if (subtree.size() > 1)
2313 {
2314 // More then one PowerMode object is not supported and is an
2315 // error
2316 BMCWEB_LOG_DEBUG(
2317 "Found more than 1 system D-Bus Power.Mode objects: {}",
2318 subtree.size());
2319 messages::internalError(asyncResp->res);
2320 return;
2321 }
2322 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2323 {
2324 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2325 messages::internalError(asyncResp->res);
2326 return;
2327 }
2328 const std::string& path = subtree[0].first;
2329 const std::string& service = subtree[0].second.begin()->first;
2330 if (service.empty())
2331 {
2332 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2333 messages::internalError(asyncResp->res);
2334 return;
2335 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002336
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002337 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002338
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002339 // Set the Power Mode property
2340 setDbusProperty(asyncResp, "PowerMode", service, path,
2341 "xyz.openbmc_project.Control.Power.Mode",
2342 "PowerMode", powerMode);
2343 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002344}
2345
2346/**
Yong Li51709ff2019-09-30 14:13:04 +08002347 * @brief Translates watchdog timeout action DBUS property value to redfish.
2348 *
2349 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2350 *
2351 * @return Returns as a string, the timeout action in Redfish terms. If
2352 * translation cannot be done, returns an empty string.
2353 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002354inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002355{
2356 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2357 {
2358 return "None";
2359 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002360 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002361 {
2362 return "ResetSystem";
2363 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002364 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002365 {
2366 return "PowerDown";
2367 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002368 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002369 {
2370 return "PowerCycle";
2371 }
2372
2373 return "";
2374}
2375
2376/**
Yong Lic45f0082019-10-10 14:19:01 +08002377 *@brief Translates timeout action from Redfish to DBUS property value.
2378 *
2379 *@param[in] rfAction The timeout action in Redfish.
2380 *
2381 *@return Returns as a string, the time_out action as expected by DBUS.
2382 *If translation cannot be done, returns an empty string.
2383 */
2384
Ed Tanous23a21a12020-07-25 04:45:05 +00002385inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002386{
2387 if (rfAction == "None")
2388 {
2389 return "xyz.openbmc_project.State.Watchdog.Action.None";
2390 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002391 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002392 {
2393 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2394 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002395 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002396 {
2397 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2398 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002399 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002400 {
2401 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2402 }
2403
2404 return "";
2405}
2406
2407/**
Yong Li51709ff2019-09-30 14:13:04 +08002408 * @brief Retrieves host watchdog timer properties over DBUS
2409 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002410 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002411 *
2412 * @return None.
2413 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002414inline void getHostWatchdogTimer(
2415 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002416{
Ed Tanous62598e32023-07-17 17:06:25 -07002417 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002418 dbus::utility::getAllProperties(
2419 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002420 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002421 [asyncResp](const boost::system::error_code& ec,
2422 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002423 if (ec)
2424 {
2425 // watchdog service is stopped
2426 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2427 return;
2428 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002429
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002430 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002431
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002432 nlohmann::json& hostWatchdogTimer =
2433 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002434
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002435 // watchdog service is running/enabled
2436 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002437
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002438 const bool* enabled = nullptr;
2439 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002440
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002441 const bool success = sdbusplus::unpackPropertiesNoThrow(
2442 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2443 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002444
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002445 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002446 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002447 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002448 return;
2449 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002450
2451 if (enabled != nullptr)
2452 {
2453 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2454 }
2455
2456 if (expireAction != nullptr)
2457 {
2458 std::string action = dbusToRfWatchdogAction(*expireAction);
2459 if (action.empty())
2460 {
2461 messages::internalError(asyncResp->res);
2462 return;
2463 }
2464 hostWatchdogTimer["TimeoutAction"] = action;
2465 }
2466 });
Yong Li51709ff2019-09-30 14:13:04 +08002467}
2468
2469/**
Yong Lic45f0082019-10-10 14:19:01 +08002470 * @brief Sets Host WatchDog Timer properties.
2471 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002472 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002473 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2474 * RF request.
2475 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2476 *
2477 * @return None.
2478 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002479inline void setWDTProperties(
2480 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2481 const std::optional<bool> wdtEnable,
2482 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002483{
Ed Tanous62598e32023-07-17 17:06:25 -07002484 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002485
2486 if (wdtTimeOutAction)
2487 {
2488 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2489 // check if TimeOut Action is Valid
2490 if (wdtTimeOutActStr.empty())
2491 {
Ed Tanous62598e32023-07-17 17:06:25 -07002492 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2493 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002494 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002495 "TimeoutAction");
2496 return;
2497 }
2498
Ginu Georgee93abac2024-06-14 17:35:27 +05302499 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2500 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002501 sdbusplus::message::object_path(
2502 "/xyz/openbmc_project/watchdog/host0"),
2503 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302504 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002505 }
2506
2507 if (wdtEnable)
2508 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302509 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2510 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002511 sdbusplus::message::object_path(
2512 "/xyz/openbmc_project/watchdog/host0"),
2513 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302514 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002515 }
2516}
2517
Chris Cain37bbf982021-09-20 10:53:09 -05002518/**
2519 * @brief Parse the Idle Power Saver properties into json
2520 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002521 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002522 * @param[in] properties IPS property data from DBus.
2523 *
2524 * @return true if successful
2525 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002526inline bool parseIpsProperties(
2527 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2528 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002529{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002530 const bool* enabled = nullptr;
2531 const uint8_t* enterUtilizationPercent = nullptr;
2532 const uint64_t* enterDwellTime = nullptr;
2533 const uint8_t* exitUtilizationPercent = nullptr;
2534 const uint64_t* exitDwellTime = nullptr;
2535
2536 const bool success = sdbusplus::unpackPropertiesNoThrow(
2537 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002538 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2539 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2540 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002541
2542 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002543 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002544 return false;
2545 }
2546
2547 if (enabled != nullptr)
2548 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002549 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002550 }
2551
2552 if (enterUtilizationPercent != nullptr)
2553 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002554 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002555 *enterUtilizationPercent;
2556 }
2557
2558 if (enterDwellTime != nullptr)
2559 {
2560 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002561 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002562 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2563 .count();
2564 }
2565
2566 if (exitUtilizationPercent != nullptr)
2567 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002568 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002569 *exitUtilizationPercent;
2570 }
2571
2572 if (exitDwellTime != nullptr)
2573 {
2574 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002575 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002576 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2577 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002578 }
2579
2580 return true;
2581}
2582
2583/**
2584 * @brief Retrieves host watchdog timer properties over DBUS
2585 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002586 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002587 *
2588 * @return None.
2589 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002590inline void getIdlePowerSaver(
2591 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002592{
Ed Tanous62598e32023-07-17 17:06:25 -07002593 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002594
2595 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002596 constexpr std::array<std::string_view, 1> interfaces = {
2597 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2598 dbus::utility::getSubTree(
2599 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002600 [asyncResp](const boost::system::error_code& ec,
2601 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002602 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002603 {
Ed Tanous62598e32023-07-17 17:06:25 -07002604 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002605 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2606 ec);
2607 messages::internalError(asyncResp->res);
2608 return;
2609 }
2610 if (subtree.empty())
2611 {
2612 // This is an optional interface so just return
2613 // if there is no instance found
2614 BMCWEB_LOG_DEBUG("No instances found");
2615 return;
2616 }
2617 if (subtree.size() > 1)
2618 {
2619 // More then one PowerIdlePowerSaver object is not supported and
2620 // is an error
2621 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2622 "Power.IdlePowerSaver objects: {}",
2623 subtree.size());
2624 messages::internalError(asyncResp->res);
2625 return;
2626 }
2627 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2628 {
2629 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2630 messages::internalError(asyncResp->res);
2631 return;
2632 }
2633 const std::string& path = subtree[0].first;
2634 const std::string& service = subtree[0].second.begin()->first;
2635 if (service.empty())
2636 {
2637 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002638 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002639 return;
2640 }
2641
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002642 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002643 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002644 *crow::connections::systemBus, service, path,
2645 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2646 [asyncResp](
2647 const boost::system::error_code& ec2,
2648 const dbus::utility::DBusPropertiesMap& properties) {
2649 if (ec2)
2650 {
2651 BMCWEB_LOG_ERROR(
2652 "DBUS response error on IdlePowerSaver GetAll: {}",
2653 ec2);
2654 messages::internalError(asyncResp->res);
2655 return;
2656 }
2657
2658 if (!parseIpsProperties(asyncResp, properties))
2659 {
2660 messages::internalError(asyncResp->res);
2661 return;
2662 }
2663 });
George Liue99073f2022-12-09 11:06:16 +08002664 });
Chris Cain37bbf982021-09-20 10:53:09 -05002665
Ed Tanous62598e32023-07-17 17:06:25 -07002666 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002667}
2668
2669/**
2670 * @brief Sets Idle Power Saver properties.
2671 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002672 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002673 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2674 * RF request.
2675 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2676 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2677 * before entering idle state.
2678 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2679 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2680 * before exiting idle state
2681 *
2682 * @return None.
2683 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002684inline void setIdlePowerSaver(
2685 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2686 const std::optional<bool> ipsEnable,
2687 const std::optional<uint8_t> ipsEnterUtil,
2688 const std::optional<uint64_t> ipsEnterTime,
2689 const std::optional<uint8_t> ipsExitUtil,
2690 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002691{
Ed Tanous62598e32023-07-17 17:06:25 -07002692 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002693
2694 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002695 constexpr std::array<std::string_view, 1> interfaces = {
2696 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2697 dbus::utility::getSubTree(
2698 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002699 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002700 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002701 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002702 if (ec)
2703 {
2704 BMCWEB_LOG_ERROR(
2705 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2706 ec);
2707 messages::internalError(asyncResp->res);
2708 return;
2709 }
2710 if (subtree.empty())
2711 {
2712 // This is an optional D-Bus object, but user attempted to patch
2713 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2714 "IdlePowerSaver");
2715 return;
2716 }
2717 if (subtree.size() > 1)
2718 {
2719 // More then one PowerIdlePowerSaver object is not supported and
2720 // is an error
2721 BMCWEB_LOG_DEBUG(
2722 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2723 subtree.size());
2724 messages::internalError(asyncResp->res);
2725 return;
2726 }
2727 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2728 {
2729 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2730 messages::internalError(asyncResp->res);
2731 return;
2732 }
2733 const std::string& path = subtree[0].first;
2734 const std::string& service = subtree[0].second.begin()->first;
2735 if (service.empty())
2736 {
2737 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2738 messages::internalError(asyncResp->res);
2739 return;
2740 }
Chris Cain37bbf982021-09-20 10:53:09 -05002741
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002742 // Valid Power IdlePowerSaver object found, now set any values that
2743 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002744
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002745 if (ipsEnable)
2746 {
2747 setDbusProperty(
2748 asyncResp, "IdlePowerSaver/Enabled", service, path,
2749 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2750 "Enabled", *ipsEnable);
2751 }
2752 if (ipsEnterUtil)
2753 {
2754 setDbusProperty(
2755 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2756 service, path,
2757 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2758 "EnterUtilizationPercent", *ipsEnterUtil);
2759 }
2760 if (ipsEnterTime)
2761 {
2762 // Convert from seconds into milliseconds for DBus
2763 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2764 setDbusProperty(
2765 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2766 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2767 "EnterDwellTime", timeMilliseconds);
2768 }
2769 if (ipsExitUtil)
2770 {
2771 setDbusProperty(
2772 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2773 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2774 "ExitUtilizationPercent", *ipsExitUtil);
2775 }
2776 if (ipsExitTime)
2777 {
2778 // Convert from seconds into milliseconds for DBus
2779 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2780 setDbusProperty(
2781 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2782 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2783 "ExitDwellTime", timeMilliseconds);
2784 }
2785 });
Chris Cain37bbf982021-09-20 10:53:09 -05002786
Ed Tanous62598e32023-07-17 17:06:25 -07002787 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002788}
2789
Ed Tanousc1e219d2023-06-07 10:34:33 -07002790inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002791 crow::App& app, const crow::Request& req,
2792 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2793{
2794 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2795 {
2796 return;
2797 }
2798 asyncResp->res.addHeader(
2799 boost::beast::http::field::link,
2800 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2801}
2802
Ed Tanousc1e219d2023-06-07 10:34:33 -07002803inline void handleComputerSystemCollectionGet(
2804 crow::App& app, const crow::Request& req,
2805 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2806{
2807 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2808 {
2809 return;
2810 }
2811
2812 asyncResp->res.addHeader(
2813 boost::beast::http::field::link,
2814 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2815 asyncResp->res.jsonValue["@odata.type"] =
2816 "#ComputerSystemCollection.ComputerSystemCollection";
2817 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2818 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2819
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002820 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002821}
2822
Yong Lic45f0082019-10-10 14:19:01 +08002823/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002824 * Function transceives data with dbus directly.
2825 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002826inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002827{
Patrick Williams89492a12023-05-10 07:51:34 -05002828 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2829 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2830 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002832 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002833
Ed Tanous177612a2025-02-14 15:16:09 -08002834 dbus::utility::async_method_call(
2835 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002836 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002837 if (ec)
2838 {
2839 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2840 messages::internalError(asyncResp->res);
2841 return;
2842 }
2843 messages::success(asyncResp->res);
2844 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002845 serviceName, objectPath, interfaceName, method);
2846}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002847
Ed Tanousc1e219d2023-06-07 10:34:33 -07002848inline void handleComputerSystemResetActionPost(
2849 crow::App& app, const crow::Request& req,
2850 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2851 const std::string& systemName)
2852{
2853 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2854 {
2855 return;
2856 }
Gunnar Millsdd7090e2024-07-30 15:23:05 -05002857
2858 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2859 {
2860 if (systemName == "hypervisor")
2861 {
2862 handleHypervisorSystemResetPost(req, asyncResp);
2863 return;
2864 }
2865 }
2866
Ed Tanous253f11b2024-05-16 09:38:31 -07002867 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002868 {
2869 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2870 systemName);
2871 return;
2872 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002873 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002874 {
2875 // Option currently returns no systems. TBD
2876 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2877 systemName);
2878 return;
2879 }
2880 std::string resetType;
2881 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2882 {
2883 return;
2884 }
2885
2886 // Get the command and host vs. chassis
2887 std::string command;
2888 bool hostCommand = true;
2889 if ((resetType == "On") || (resetType == "ForceOn"))
2890 {
2891 command = "xyz.openbmc_project.State.Host.Transition.On";
2892 hostCommand = true;
2893 }
2894 else if (resetType == "ForceOff")
2895 {
2896 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2897 hostCommand = false;
2898 }
2899 else if (resetType == "ForceRestart")
2900 {
2901 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2902 hostCommand = true;
2903 }
2904 else if (resetType == "GracefulShutdown")
2905 {
2906 command = "xyz.openbmc_project.State.Host.Transition.Off";
2907 hostCommand = true;
2908 }
2909 else if (resetType == "GracefulRestart")
2910 {
2911 command =
2912 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2913 hostCommand = true;
2914 }
2915 else if (resetType == "PowerCycle")
2916 {
2917 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2918 hostCommand = true;
2919 }
2920 else if (resetType == "Nmi")
2921 {
2922 doNMI(asyncResp);
2923 return;
2924 }
2925 else
2926 {
2927 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2928 return;
2929 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002930 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002931
2932 if (hostCommand)
2933 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302934 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002935 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302936 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002937 }
2938 else
2939 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302940 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08002941 statePath / "chassis0",
2942 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302943 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002944 }
2945}
2946
Ed Tanousc1e219d2023-06-07 10:34:33 -07002947inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002948 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002949 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2950 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002951{
2952 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2953 {
2954 return;
2955 }
2956
2957 asyncResp->res.addHeader(
2958 boost::beast::http::field::link,
2959 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2960}
2961
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002962inline void afterPortRequest(
2963 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2964 const boost::system::error_code& ec,
2965 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2966{
2967 if (ec)
2968 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002969 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002970 messages::internalError(asyncResp->res);
2971 return;
2972 }
2973 for (const auto& data : socketData)
2974 {
2975 const std::string& socketPath = get<0>(data);
2976 const std::string& protocolName = get<1>(data);
2977 bool isProtocolEnabled = get<2>(data);
2978 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2979 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2980 // need to retrieve port number for
2981 // obmc-console-ssh service
2982 if (protocolName == "SSH")
2983 {
2984 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002985 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002986 int portNumber) {
2987 if (ec1)
2988 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002989 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002990 messages::internalError(asyncResp->res);
2991 return;
2992 }
2993 nlohmann::json& dataJson1 =
2994 asyncResp->res.jsonValue["SerialConsole"];
2995 dataJson1[protocolName]["Port"] = portNumber;
2996 });
2997 }
2998 }
2999}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003000
Patrick Williams504af5a2025-02-03 14:29:03 -05003001inline void handleComputerSystemGet(
3002 crow::App& app, const crow::Request& req,
3003 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3004 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003005{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003006 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3007 {
3008 return;
3009 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003010
Ed Tanous25b54db2024-04-17 15:40:31 -07003011 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003012 {
3013 // Option currently returns no systems. TBD
3014 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3015 systemName);
3016 return;
3017 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003018
Gunnar Mills68896202024-08-21 11:34:20 -05003019 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003020 {
Gunnar Mills68896202024-08-21 11:34:20 -05003021 if (systemName == "hypervisor")
3022 {
3023 handleHypervisorSystemGet(asyncResp);
3024 return;
3025 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003026 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003027
Ed Tanous253f11b2024-05-16 09:38:31 -07003028 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003029 {
3030 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3031 systemName);
3032 return;
3033 }
3034 asyncResp->res.addHeader(
3035 boost::beast::http::field::link,
3036 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3037 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003038 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003039 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3040 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanous539d8c62024-06-19 14:38:27 -07003041 asyncResp->res.jsonValue["SystemType"] =
3042 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003043 asyncResp->res.jsonValue["Description"] = "Computer System";
3044 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003045 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003046 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003047 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3048 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003049
Ed Tanous253f11b2024-05-16 09:38:31 -07003050 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3051 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3052 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3053 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3054 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3055 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003056 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003057 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3058 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003059
Ed Tanousc1e219d2023-06-07 10:34:33 -07003060 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003061 boost::urls::format(
3062 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3063 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003064 asyncResp->res
3065 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003066 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3067 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003068
Ed Tanous253f11b2024-05-16 09:38:31 -07003069 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3070 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3071 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3072 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003073
Ed Tanousc1e219d2023-06-07 10:34:33 -07003074 nlohmann::json::array_t managedBy;
3075 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003076 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3077 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003078 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003079 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3080 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003081
Ed Tanousc1e219d2023-06-07 10:34:33 -07003082 // Fill in SerialConsole info
3083 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3084 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003085
Ed Tanousc1e219d2023-06-07 10:34:33 -07003086 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3087 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3088 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3089 "Press ~. to exit console";
3090 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3091 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003092
Ed Tanous25b54db2024-04-17 15:40:31 -07003093 if constexpr (BMCWEB_KVM)
3094 {
3095 // Fill in GraphicalConsole info
3096 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3097 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3098 4;
3099 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3100 nlohmann::json::array_t({"KVMIP"});
3101 }
James Feistb49ac872019-05-21 15:12:01 -07003102
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003103 getMainChassisId(
3104 asyncResp, [](const std::string& chassisId,
3105 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3106 nlohmann::json::array_t chassisArray;
3107 nlohmann::json& chassis = chassisArray.emplace_back();
3108 chassis["@odata.id"] =
3109 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3110 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3111 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003112
George Liu59a17e42022-10-08 09:27:47 +08003113 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003114 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3115 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003116 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003117 getHostState(asyncResp);
3118 getBootProperties(asyncResp);
3119 getBootProgress(asyncResp);
3120 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003121 pcie_util::getPCIeDeviceList(asyncResp,
3122 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003123 getHostWatchdogTimer(asyncResp);
3124 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003125 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003126 getAutomaticRetryPolicy(asyncResp);
3127 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003128 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3129 {
3130 getProvisioningStatus(asyncResp);
3131 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003132 getTrustedModuleRequiredToBoot(asyncResp);
3133 getPowerMode(asyncResp);
3134 getIdlePowerSaver(asyncResp);
3135}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003136
Ed Tanousc1e219d2023-06-07 10:34:33 -07003137inline void handleComputerSystemPatch(
3138 crow::App& app, const crow::Request& req,
3139 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3140 const std::string& systemName)
3141{
3142 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3143 {
3144 return;
3145 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003146 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003147 {
3148 // Option currently returns no systems. TBD
3149 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3150 systemName);
3151 return;
3152 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003153 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003154 {
3155 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3156 systemName);
3157 return;
3158 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003159
Ed Tanousc1e219d2023-06-07 10:34:33 -07003160 asyncResp->res.addHeader(
3161 boost::beast::http::field::link,
3162 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003163
Ed Tanousc1e219d2023-06-07 10:34:33 -07003164 std::optional<bool> locationIndicatorActive;
3165 std::optional<std::string> indicatorLed;
3166 std::optional<std::string> assetTag;
3167 std::optional<std::string> powerRestorePolicy;
3168 std::optional<std::string> powerMode;
3169 std::optional<bool> wdtEnable;
3170 std::optional<std::string> wdtTimeOutAction;
3171 std::optional<std::string> bootSource;
3172 std::optional<std::string> bootType;
3173 std::optional<std::string> bootEnable;
3174 std::optional<std::string> bootAutomaticRetry;
3175 std::optional<uint32_t> bootAutomaticRetryAttempts;
3176 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003177 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003178 std::optional<bool> ipsEnable;
3179 std::optional<uint8_t> ipsEnterUtil;
3180 std::optional<uint64_t> ipsEnterTime;
3181 std::optional<uint8_t> ipsExitUtil;
3182 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003183
Patrick Williams504af5a2025-02-03 14:29:03 -05003184 if (!json_util::readJsonPatch( //
3185 req, asyncResp->res, //
3186 "AssetTag", assetTag, //
3187 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts, //
3188 "Boot/AutomaticRetryConfig", bootAutomaticRetry, //
3189 "Boot/BootSourceOverrideEnabled", bootEnable, //
3190 "Boot/BootSourceOverrideMode", bootType, //
3191 "Boot/BootSourceOverrideTarget", bootSource, //
3192 "Boot/StopBootOnFault", stopBootOnFault, //
Myung Baeafc474a2024-10-09 00:53:29 -07003193 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired, //
Patrick Williams504af5a2025-02-03 14:29:03 -05003194 "HostWatchdogTimer/FunctionEnabled", wdtEnable, //
3195 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction, //
3196 "IdlePowerSaver/Enabled", ipsEnable, //
3197 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime, //
3198 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil, //
3199 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime, //
3200 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil, //
3201 "IndicatorLED", indicatorLed, //
3202 "LocationIndicatorActive", locationIndicatorActive, //
3203 "PowerMode", powerMode, //
3204 "PowerRestorePolicy", powerRestorePolicy //
Myung Baeafc474a2024-10-09 00:53:29 -07003205 ))
Ed Tanousab344222024-08-07 18:01:23 -07003206 {
3207 return;
3208 }
James Feistb49ac872019-05-21 15:12:01 -07003209
Ed Tanousc1e219d2023-06-07 10:34:33 -07003210 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003211
Ed Tanousc1e219d2023-06-07 10:34:33 -07003212 if (assetTag)
3213 {
3214 setAssetTag(asyncResp, *assetTag);
3215 }
James Feistb49ac872019-05-21 15:12:01 -07003216
Ed Tanousc1e219d2023-06-07 10:34:33 -07003217 if (wdtEnable || wdtTimeOutAction)
3218 {
3219 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3220 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003221
Ed Tanousc1e219d2023-06-07 10:34:33 -07003222 if (bootSource || bootType || bootEnable)
3223 {
3224 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3225 }
3226 if (bootAutomaticRetry)
3227 {
3228 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3229 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003230
Ed Tanousc1e219d2023-06-07 10:34:33 -07003231 if (bootAutomaticRetryAttempts)
3232 {
3233 setAutomaticRetryAttempts(asyncResp,
3234 bootAutomaticRetryAttempts.value());
3235 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003236
Ed Tanousc1e219d2023-06-07 10:34:33 -07003237 if (bootTrustedModuleRequired)
3238 {
3239 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3240 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003241
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003242 if (stopBootOnFault)
3243 {
3244 setStopBootOnFault(asyncResp, *stopBootOnFault);
3245 }
3246
Ed Tanousc1e219d2023-06-07 10:34:33 -07003247 if (locationIndicatorActive)
3248 {
George Liu59a17e42022-10-08 09:27:47 +08003249 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003250 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003251
Ed Tanousc1e219d2023-06-07 10:34:33 -07003252 // TODO (Gunnar): Remove IndicatorLED after enough time has
3253 // passed
3254 if (indicatorLed)
3255 {
3256 setIndicatorLedState(asyncResp, *indicatorLed);
3257 asyncResp->res.addHeader(boost::beast::http::field::warning,
3258 "299 - \"IndicatorLED is deprecated. Use "
3259 "LocationIndicatorActive instead.\"");
3260 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003261
Ed Tanousc1e219d2023-06-07 10:34:33 -07003262 if (powerRestorePolicy)
3263 {
3264 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3265 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003266
Ed Tanousc1e219d2023-06-07 10:34:33 -07003267 if (powerMode)
3268 {
3269 setPowerMode(asyncResp, *powerMode);
3270 }
Chris Cain37bbf982021-09-20 10:53:09 -05003271
Ed Tanousc1e219d2023-06-07 10:34:33 -07003272 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3273 {
3274 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3275 ipsExitUtil, ipsExitTime);
3276 }
3277}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303278
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003279inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003280 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003281 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003282 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003283{
3284 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3285 {
3286 return;
3287 }
3288 asyncResp->res.addHeader(
3289 boost::beast::http::field::link,
3290 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3291}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003292
3293/**
3294 * @brief Translates allowed host transitions to redfish string
3295 *
3296 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3297 * @param[out] allowableValues The translated host transition(s)
3298 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303299 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003300 * allowableValues. If translation not possible, does nothing to
3301 * allowableValues.
3302 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003303inline void dbusToRfAllowedHostTransitions(
3304 const std::string& dbusAllowedHostTran,
3305 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003306{
3307 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3308 {
3309 allowableValues.emplace_back(resource::ResetType::On);
3310 allowableValues.emplace_back(resource::ResetType::ForceOn);
3311 }
3312 else if (dbusAllowedHostTran ==
3313 "xyz.openbmc_project.State.Host.Transition.Off")
3314 {
3315 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3316 }
3317 else if (dbusAllowedHostTran ==
3318 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3319 {
3320 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3321 }
3322 else if (dbusAllowedHostTran ==
3323 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3324 {
3325 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3326 }
3327 else
3328 {
3329 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3330 }
3331}
3332
3333inline void afterGetAllowedHostTransitions(
3334 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3335 const boost::system::error_code& ec,
3336 const std::vector<std::string>& allowedHostTransitions)
3337{
3338 nlohmann::json::array_t allowableValues;
3339
3340 // Supported on all systems currently
3341 allowableValues.emplace_back(resource::ResetType::ForceOff);
3342 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3343 allowableValues.emplace_back(resource::ResetType::Nmi);
3344
3345 if (ec)
3346 {
Ed Tanouse715d142024-03-07 15:47:37 -08003347 if ((ec.value() ==
3348 boost::system::linux_error::bad_request_descriptor) ||
3349 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003350 {
3351 // Property not implemented so just return defaults
3352 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3353 allowableValues.emplace_back(resource::ResetType::On);
3354 allowableValues.emplace_back(resource::ResetType::ForceOn);
3355 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3356 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3357 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3358 }
3359 else
3360 {
3361 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3362 messages::internalError(asyncResp->res);
3363 return;
3364 }
3365 }
3366 else
3367 {
3368 for (const std::string& transition : allowedHostTransitions)
3369 {
3370 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3371 dbusToRfAllowedHostTransitions(transition, allowableValues);
3372 }
3373 }
3374
3375 nlohmann::json::object_t parameter;
3376 parameter["Name"] = "ResetType";
3377 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003378 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003379 parameter["AllowableValues"] = std::move(allowableValues);
3380 nlohmann::json::array_t parameters;
3381 parameters.emplace_back(std::move(parameter));
3382 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3383}
3384
Ed Tanousc1e219d2023-06-07 10:34:33 -07003385inline void handleSystemCollectionResetActionGet(
3386 crow::App& app, const crow::Request& req,
3387 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3388 const std::string& systemName)
3389{
3390 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3391 {
3392 return;
3393 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003394 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003395 {
3396 // Option currently returns no systems. TBD
3397 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3398 systemName);
3399 return;
3400 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003401
Gunnar Mills68896202024-08-21 11:34:20 -05003402 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003403 {
Gunnar Mills68896202024-08-21 11:34:20 -05003404 if (systemName == "hypervisor")
3405 {
3406 handleHypervisorResetActionGet(asyncResp);
3407 return;
3408 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003409 }
3410
Ed Tanous253f11b2024-05-16 09:38:31 -07003411 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003412 {
3413 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3414 systemName);
3415 return;
3416 }
3417
3418 asyncResp->res.addHeader(
3419 boost::beast::http::field::link,
3420 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3421
3422 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003423 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3424 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003425 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3426 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3427 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3428
Andrew Geissler33e1f122024-02-26 21:10:16 -06003429 // Look to see if system defines AllowedHostTransitions
Ed Tanousdeae6a72024-11-11 21:58:57 -08003430 dbus::utility::getProperty<std::vector<std::string>>(
3431 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
3432 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
Andrew Geissler33e1f122024-02-26 21:10:16 -06003433 [asyncResp](const boost::system::error_code& ec,
3434 const std::vector<std::string>& allowedHostTransitions) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003435 afterGetAllowedHostTransitions(asyncResp, ec,
3436 allowedHostTransitions);
3437 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003438}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303439/**
3440 * SystemResetActionInfo derived class for delivering Computer Systems
3441 * ResetType AllowableValues using ResetInfo schema.
3442 */
Ed Tanous100afe52023-06-07 13:30:46 -07003443inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303444{
Ed Tanous100afe52023-06-07 13:30:46 -07003445 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3446 .privileges(redfish::privileges::headComputerSystemCollection)
3447 .methods(boost::beast::http::verb::head)(
3448 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3449
3450 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3451 .privileges(redfish::privileges::getComputerSystemCollection)
3452 .methods(boost::beast::http::verb::get)(
3453 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3454
3455 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3456 .privileges(redfish::privileges::headComputerSystem)
3457 .methods(boost::beast::http::verb::head)(
3458 std::bind_front(handleComputerSystemHead, std::ref(app)));
3459
3460 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3461 .privileges(redfish::privileges::getComputerSystem)
3462 .methods(boost::beast::http::verb::get)(
3463 std::bind_front(handleComputerSystemGet, std::ref(app)));
3464
3465 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3466 .privileges(redfish::privileges::patchComputerSystem)
3467 .methods(boost::beast::http::verb::patch)(
3468 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3469
3470 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3471 .privileges(redfish::privileges::postComputerSystem)
3472 .methods(boost::beast::http::verb::post)(std::bind_front(
3473 handleComputerSystemResetActionPost, std::ref(app)));
3474
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003475 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003476 .privileges(redfish::privileges::headActionInfo)
3477 .methods(boost::beast::http::verb::head)(std::bind_front(
3478 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003479 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003480 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003481 .methods(boost::beast::http::verb::get)(std::bind_front(
3482 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003483}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003484} // namespace redfish