blob: 0301110fc0d3c784d90a0aa702ae09b846c3dbd9 [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 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001184 if (ec.value() != EBADR)
1185 {
1186 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1187 messages::internalError(asyncResp->res);
1188 }
1189 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001190 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001191
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001192 const uint32_t* attemptsLeft = nullptr;
1193 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001194
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001195 const bool success = sdbusplus::unpackPropertiesNoThrow(
1196 dbus_utils::UnpackErrorPrinter(), propertiesList,
1197 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001198
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001199 if (!success)
1200 {
1201 messages::internalError(asyncResp->res);
1202 return;
1203 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001204
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001205 if (attemptsLeft != nullptr)
1206 {
1207 asyncResp->res
1208 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1209 *attemptsLeft;
1210 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001211
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001212 if (retryAttempts != nullptr)
1213 {
1214 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1215 *retryAttempts;
1216 }
1217 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001218}
1219
1220/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001221 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1222 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001223 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001224 *
1225 * @return None.
1226 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001227inline void getAutomaticRetryPolicy(
1228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001229{
Ed Tanous62598e32023-07-17 17:06:25 -07001230 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001231
Ed Tanousdeae6a72024-11-11 21:58:57 -08001232 dbus::utility::getProperty<bool>(
1233 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001234 "/xyz/openbmc_project/control/host0/auto_reboot",
1235 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001236 [asyncResp](const boost::system::error_code& ec,
1237 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001238 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001239 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001240 if (ec.value() != EBADR)
1241 {
1242 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1243 messages::internalError(asyncResp->res);
1244 }
1245 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001246 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001247
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001248 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1249 if (autoRebootEnabled)
1250 {
1251 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1252 "RetryAttempts";
1253 }
1254 else
1255 {
1256 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1257 "Disabled";
1258 }
1259 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001260
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001261 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1262 // and RetryAttempts. OpenBMC only supports Disabled and
1263 // RetryAttempts.
1264 nlohmann::json::array_t allowed;
1265 allowed.emplace_back("Disabled");
1266 allowed.emplace_back("RetryAttempts");
1267 asyncResp->res
1268 .jsonValue["Boot"]
1269 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1270 std::move(allowed);
1271 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001272}
1273
1274/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001275 * @brief Sets RetryAttempts
1276 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001277 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001278 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1279 *
1280 *@return None.
1281 */
1282
Ed Tanousac106bf2023-06-07 09:24:59 -07001283inline void setAutomaticRetryAttempts(
1284 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1285 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001286{
Ed Tanous62598e32023-07-17 17:06:25 -07001287 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001288 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301289 asyncResp, "Boot/AutomaticRetryAttempts",
1290 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001291 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001292 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301293 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001294}
1295
Ed Tanous8d69c662023-06-21 10:29:06 -07001296inline computer_system::PowerRestorePolicyTypes
1297 redfishPowerRestorePolicyFromDbus(std::string_view value)
1298{
1299 if (value ==
1300 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1301 {
1302 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1303 }
1304 if (value ==
1305 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1306 {
1307 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1308 }
1309 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001310 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001311 {
1312 return computer_system::PowerRestorePolicyTypes::LastState;
1313 }
1314 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1315 {
1316 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1317 }
1318 return computer_system::PowerRestorePolicyTypes::Invalid;
1319}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001320/**
George Liuc6a620f2020-04-10 17:18:11 +08001321 * @brief Retrieves power restore policy over DBUS.
1322 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001323 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001324 *
1325 * @return None.
1326 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001327inline void getPowerRestorePolicy(
1328 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001329{
Ed Tanous62598e32023-07-17 17:06:25 -07001330 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001331
Ed Tanousdeae6a72024-11-11 21:58:57 -08001332 dbus::utility::getProperty<std::string>(
1333 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001334 "/xyz/openbmc_project/control/host0/power_restore_policy",
1335 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001336 [asyncResp](const boost::system::error_code& ec,
1337 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001338 if (ec)
1339 {
1340 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1341 return;
1342 }
1343 computer_system::PowerRestorePolicyTypes restore =
1344 redfishPowerRestorePolicyFromDbus(policy);
1345 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1346 {
1347 messages::internalError(asyncResp->res);
1348 return;
1349 }
George Liuc6a620f2020-04-10 17:18:11 +08001350
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001351 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1352 });
George Liuc6a620f2020-04-10 17:18:11 +08001353}
1354
1355/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001356 * @brief Stop Boot On Fault over DBUS.
1357 *
1358 * @param[in] asyncResp Shared pointer for generating response message.
1359 *
1360 * @return None.
1361 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001362inline void getStopBootOnFault(
1363 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001364{
Ed Tanous62598e32023-07-17 17:06:25 -07001365 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001366
Ed Tanousdeae6a72024-11-11 21:58:57 -08001367 dbus::utility::getProperty<bool>(
1368 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001369 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1370 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001371 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001372 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001373 if (ec.value() != EBADR)
1374 {
1375 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1376 messages::internalError(asyncResp->res);
1377 }
1378 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001379 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001380
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001381 if (value)
1382 {
1383 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1384 computer_system::StopBootOnFault::AnyFault;
1385 }
1386 else
1387 {
1388 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1389 computer_system::StopBootOnFault::Never;
1390 }
1391 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001392}
1393
1394/**
Ali Ahmed19817712021-06-29 17:01:52 -05001395 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1396 * TPM is required for booting the host.
1397 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001398 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001399 *
1400 * @return None.
1401 */
1402inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001403 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001404{
Ed Tanous62598e32023-07-17 17:06:25 -07001405 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001406 constexpr std::array<std::string_view, 1> interfaces = {
1407 "xyz.openbmc_project.Control.TPM.Policy"};
1408 dbus::utility::getSubTree(
1409 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001410 [asyncResp](const boost::system::error_code& ec,
1411 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001412 if (ec)
Ali Ahmed19817712021-06-29 17:01:52 -05001413 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001414 BMCWEB_LOG_DEBUG(
1415 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1416 // This is an optional D-Bus object so just return if
1417 // error occurs
1418 return;
1419 }
1420 if (subtree.empty())
1421 {
1422 // As noted above, this is an optional interface so just return
1423 // if there is no instance found
1424 return;
1425 }
1426
1427 /* When there is more than one TPMEnable object... */
1428 if (subtree.size() > 1)
1429 {
1430 BMCWEB_LOG_DEBUG(
1431 "DBUS response has more than 1 TPM Enable object:{}",
1432 subtree.size());
1433 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001434 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001435 return;
1436 }
1437
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001438 // Make sure the Dbus response map has a service and objectPath
1439 // field
1440 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
Ali Ahmed19817712021-06-29 17:01:52 -05001441 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001442 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1443 messages::internalError(asyncResp->res);
1444 return;
Ali Ahmed19817712021-06-29 17:01:52 -05001445 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001446
1447 const std::string& path = subtree[0].first;
1448 const std::string& serv = subtree[0].second.begin()->first;
1449
1450 // Valid TPM Enable object found, now reading the current value
Ed Tanousdeae6a72024-11-11 21:58:57 -08001451 dbus::utility::getProperty<bool>(
1452 serv, path, "xyz.openbmc_project.Control.TPM.Policy",
1453 "TPMEnable",
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001454 [asyncResp](const boost::system::error_code& ec2,
1455 bool tpmRequired) {
1456 if (ec2)
1457 {
1458 BMCWEB_LOG_ERROR(
1459 "D-BUS response error on TPM.Policy Get{}", ec2);
1460 messages::internalError(asyncResp->res);
1461 return;
1462 }
1463
1464 if (tpmRequired)
1465 {
1466 asyncResp->res
1467 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1468 "Required";
1469 }
1470 else
1471 {
1472 asyncResp->res
1473 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1474 "Disabled";
1475 }
1476 });
George Liue99073f2022-12-09 11:06:16 +08001477 });
Ali Ahmed19817712021-06-29 17:01:52 -05001478}
1479
1480/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001481 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1482 * TPM is required for booting the host.
1483 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001484 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001485 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1486 *
1487 * @return None.
1488 */
1489inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001490 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001491{
Ed Tanous62598e32023-07-17 17:06:25 -07001492 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001493 constexpr std::array<std::string_view, 1> interfaces = {
1494 "xyz.openbmc_project.Control.TPM.Policy"};
1495 dbus::utility::getSubTree(
1496 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001497 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001498 tpmRequired](const boost::system::error_code& ec,
1499 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001500 if (ec)
1501 {
1502 BMCWEB_LOG_ERROR(
1503 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1504 messages::internalError(asyncResp->res);
1505 return;
1506 }
1507 if (subtree.empty())
1508 {
1509 messages::propertyValueNotInList(asyncResp->res,
1510 "ComputerSystem",
1511 "TrustedModuleRequiredToBoot");
1512 return;
1513 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001514
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001515 /* When there is more than one TPMEnable object... */
1516 if (subtree.size() > 1)
1517 {
1518 BMCWEB_LOG_DEBUG(
1519 "DBUS response has more than 1 TPM Enable object:{}",
1520 subtree.size());
1521 // Throw an internal Error and return
1522 messages::internalError(asyncResp->res);
1523 return;
1524 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001525
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001526 // Make sure the Dbus response map has a service and objectPath
1527 // field
1528 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1529 {
1530 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1531 messages::internalError(asyncResp->res);
1532 return;
1533 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001534
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001535 const std::string& path = subtree[0].first;
1536 const std::string& serv = subtree[0].second.begin()->first;
Ed Tanous002d39b2022-05-31 08:59:27 -07001537
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001538 if (serv.empty())
1539 {
1540 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1541 messages::internalError(asyncResp->res);
1542 return;
1543 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001544
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001545 // Valid TPM Enable object found, now setting the value
1546 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1547 path, "xyz.openbmc_project.Control.TPM.Policy",
1548 "TPMEnable", tpmRequired);
1549 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001550}
1551
1552/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301553 * @brief Sets boot properties into DBUS object(s).
1554 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001555 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001556 * @param[in] bootType The boot type to set.
1557 * @return Integer error code.
1558 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001559inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001560 const std::optional<std::string>& bootType)
1561{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001562 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001563
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001564 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001565 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001566 return;
1567 }
1568
1569 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001570 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001571 // Figure out which DBUS interface and property to use
1572 if (*bootType == "Legacy")
1573 {
1574 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1575 }
1576 else if (*bootType == "UEFI")
1577 {
1578 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1579 }
1580 else
1581 {
Ed Tanous62598e32023-07-17 17:06:25 -07001582 BMCWEB_LOG_DEBUG("Invalid property value for "
1583 "BootSourceOverrideMode: {}",
1584 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001585 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001586 "BootSourceOverrideMode");
1587 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001588 }
1589
1590 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001591 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001592
Ginu Georgee93abac2024-06-14 17:35:27 +05301593 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1594 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001595 sdbusplus::message::object_path(
1596 "/xyz/openbmc_project/control/host0/boot"),
1597 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301598 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001599}
1600
1601/**
1602 * @brief Sets boot properties into DBUS object(s).
1603 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001604 * @param[in] asyncResp Shared pointer for generating response
1605 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001606 * @param[in] bootType The boot type to set.
1607 * @return Integer error code.
1608 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001609inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001610 const std::optional<std::string>& bootEnable)
1611{
1612 if (!bootEnable)
1613 {
1614 return;
1615 }
1616 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001617 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001618
1619 bool bootOverrideEnable = false;
1620 bool bootOverridePersistent = false;
1621 // Figure out which DBUS interface and property to use
1622 if (*bootEnable == "Disabled")
1623 {
1624 bootOverrideEnable = false;
1625 }
1626 else if (*bootEnable == "Once")
1627 {
1628 bootOverrideEnable = true;
1629 bootOverridePersistent = false;
1630 }
1631 else if (*bootEnable == "Continuous")
1632 {
1633 bootOverrideEnable = true;
1634 bootOverridePersistent = true;
1635 }
1636 else
1637 {
Ed Tanous62598e32023-07-17 17:06:25 -07001638 BMCWEB_LOG_DEBUG(
1639 "Invalid property value for BootSourceOverrideEnabled: {}",
1640 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001641 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001642 "BootSourceOverrideEnabled");
1643 return;
1644 }
1645
1646 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001647 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001648
Ginu Georgee93abac2024-06-14 17:35:27 +05301649 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1650 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001651 sdbusplus::message::object_path(
1652 "/xyz/openbmc_project/control/host0/boot"),
1653 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301654 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001655
1656 if (!bootOverrideEnable)
1657 {
1658 return;
1659 }
1660
1661 // In case boot override is enabled we need to set correct value for the
1662 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001663 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1664 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001665
Ginu Georgee93abac2024-06-14 17:35:27 +05301666 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1667 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001668 sdbusplus::message::object_path(
1669 "/xyz/openbmc_project/control/host0/boot/one_time"),
1670 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301671 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001672}
1673
1674/**
1675 * @brief Sets boot properties into DBUS object(s).
1676 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001677 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301678 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301679 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001680 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301681 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001682inline void setBootModeOrSource(
1683 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1684 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301685{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001686 std::string bootSourceStr;
1687 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001688
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001689 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301690 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001691 return;
1692 }
1693
1694 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001695 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001696 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001697 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1698 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001699 {
Ed Tanous62598e32023-07-17 17:06:25 -07001700 BMCWEB_LOG_DEBUG(
1701 "Invalid property value for BootSourceOverrideTarget: {}",
1702 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001703 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001704 "BootSourceTargetOverride");
1705 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001706 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301707
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001708 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001709 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1710 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001711
Ginu Georgee93abac2024-06-14 17:35:27 +05301712 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1713 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001714 sdbusplus::message::object_path(
1715 "/xyz/openbmc_project/control/host0/boot"),
1716 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301717 bootSourceStr);
1718 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1719 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001720 sdbusplus::message::object_path(
1721 "/xyz/openbmc_project/control/host0/boot"),
1722 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301723 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001724}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001725
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001726/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001727 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301728 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001729 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301730 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001731 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732 * @param[in] bootEnable The boot override enable from incoming RF request.
1733 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001734 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301735 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001736
Patrick Williams504af5a2025-02-03 14:29:03 -05001737inline void setBootProperties(
1738 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1739 const std::optional<std::string>& bootSource,
1740 const std::optional<std::string>& bootType,
1741 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301742{
Ed Tanous62598e32023-07-17 17:06:25 -07001743 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301744
Ed Tanousac106bf2023-06-07 09:24:59 -07001745 setBootModeOrSource(asyncResp, bootSource);
1746 setBootType(asyncResp, bootType);
1747 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301748}
1749
George Liuc6a620f2020-04-10 17:18:11 +08001750/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001751 * @brief Sets AssetTag
1752 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001753 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001754 * @param[in] assetTag "AssetTag" from request.
1755 *
1756 * @return None.
1757 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001758inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001759 const std::string& assetTag)
1760{
George Liue99073f2022-12-09 11:06:16 +08001761 constexpr std::array<std::string_view, 1> interfaces = {
1762 "xyz.openbmc_project.Inventory.Item.System"};
1763 dbus::utility::getSubTree(
1764 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001765 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001766 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001767 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001768 if (ec)
1769 {
1770 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1771 messages::internalError(asyncResp->res);
1772 return;
1773 }
1774 if (subtree.empty())
1775 {
1776 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1777 messages::internalError(asyncResp->res);
1778 return;
1779 }
1780 // Assume only 1 system D-Bus object
1781 // Throw an error if there is more than 1
1782 if (subtree.size() > 1)
1783 {
1784 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1785 messages::internalError(asyncResp->res);
1786 return;
1787 }
1788 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1789 {
1790 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1791 messages::internalError(asyncResp->res);
1792 return;
1793 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001794
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001795 const std::string& path = subtree[0].first;
1796 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001797
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001798 if (service.empty())
1799 {
1800 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1801 messages::internalError(asyncResp->res);
1802 return;
1803 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001804
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001805 setDbusProperty(asyncResp, "AssetTag", service, path,
1806 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1807 "AssetTag", assetTag);
1808 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001809}
1810
1811/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001812 * @brief Validate the specified stopBootOnFault is valid and return the
1813 * stopBootOnFault name associated with that string
1814 *
1815 * @param[in] stopBootOnFaultString String representing the desired
1816 * stopBootOnFault
1817 *
1818 * @return stopBootOnFault value or empty if incoming value is not valid
1819 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001820inline std::optional<bool> validstopBootOnFault(
1821 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001822{
1823 if (stopBootOnFaultString == "AnyFault")
1824 {
1825 return true;
1826 }
1827
1828 if (stopBootOnFaultString == "Never")
1829 {
1830 return false;
1831 }
1832
1833 return std::nullopt;
1834}
1835
1836/**
1837 * @brief Sets stopBootOnFault
1838 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001839 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001840 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1841 *
1842 * @return None.
1843 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001844inline void setStopBootOnFault(
1845 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1846 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001847{
Ed Tanous62598e32023-07-17 17:06:25 -07001848 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001849
1850 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1851 if (!stopBootEnabled)
1852 {
Ed Tanous62598e32023-07-17 17:06:25 -07001853 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1854 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001855 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001856 "StopBootOnFault");
1857 return;
1858 }
1859
Ginu Georgee93abac2024-06-14 17:35:27 +05301860 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1861 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001862 sdbusplus::message::object_path(
1863 "/xyz/openbmc_project/logging/settings"),
1864 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301865 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001866}
1867
1868/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001869 * @brief Sets automaticRetry (Auto Reboot)
1870 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001871 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001872 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1873 *
1874 * @return None.
1875 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001876inline void setAutomaticRetry(
1877 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1878 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001879{
Ed Tanous62598e32023-07-17 17:06:25 -07001880 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001881
1882 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001883 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001884
1885 if (automaticRetryConfig == "Disabled")
1886 {
1887 autoRebootEnabled = false;
1888 }
1889 else if (automaticRetryConfig == "RetryAttempts")
1890 {
1891 autoRebootEnabled = true;
1892 }
1893 else
1894 {
Ed Tanous62598e32023-07-17 17:06:25 -07001895 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1896 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001897 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001898 "AutomaticRetryConfig");
1899 return;
1900 }
1901
Ginu Georgee93abac2024-06-14 17:35:27 +05301902 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1903 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001904 sdbusplus::message::object_path(
1905 "/xyz/openbmc_project/control/host0/auto_reboot"),
1906 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301907 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001908}
1909
Ed Tanous8d69c662023-06-21 10:29:06 -07001910inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1911{
1912 if (policy == "AlwaysOn")
1913 {
1914 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1915 }
1916 if (policy == "AlwaysOff")
1917 {
1918 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1919 }
1920 if (policy == "LastState")
1921 {
1922 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1923 }
1924 return "";
1925}
1926
Gunnar Mills69f35302020-05-17 16:06:31 -05001927/**
George Liuc6a620f2020-04-10 17:18:11 +08001928 * @brief Sets power restore policy properties.
1929 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001930 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001931 * @param[in] policy power restore policy properties from request.
1932 *
1933 * @return None.
1934 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001935inline void setPowerRestorePolicy(
1936 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1937 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001938{
Ed Tanous62598e32023-07-17 17:06:25 -07001939 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001940
Ed Tanous8d69c662023-06-21 10:29:06 -07001941 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001942
Ed Tanous8d69c662023-06-21 10:29:06 -07001943 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001944 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001945 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001946 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001947 return;
1948 }
1949
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001950 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301951 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001952 sdbusplus::message::object_path(
1953 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001954 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301955 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001956}
1957
AppaRao Pulia6349912019-10-18 17:16:08 +05301958/**
1959 * @brief Retrieves provisioning status
1960 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001961 * @param[in] asyncResp Shared pointer for completing asynchronous
1962 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301963 *
1964 * @return None.
1965 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001966inline void getProvisioningStatus(
1967 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301968{
Ed Tanous62598e32023-07-17 17:06:25 -07001969 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08001970 dbus::utility::getAllProperties(
1971 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1972 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001973 [asyncResp](const boost::system::error_code& ec,
1974 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001975 nlohmann::json& oemPFR =
1976 asyncResp->res
1977 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1978 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1979 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1980 oemPFR["@odata.type"] =
1981 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001982
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001983 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05301984 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001985 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1986 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07001987 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001988 FirmwareProvisioningStatus::NotProvisioned;
1989 return;
1990 }
1991
1992 const bool* provState = nullptr;
1993 const bool* lockState = nullptr;
1994
1995 const bool success = sdbusplus::unpackPropertiesNoThrow(
1996 dbus_utils::UnpackErrorPrinter(), propertiesList,
1997 "UfmProvisioned", provState, "UfmLocked", lockState);
1998
1999 if (!success)
2000 {
2001 messages::internalError(asyncResp->res);
2002 return;
2003 }
2004
2005 if ((provState == nullptr) || (lockState == nullptr))
2006 {
2007 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2008 messages::internalError(asyncResp->res);
2009 return;
2010 }
2011
2012 if (*provState)
2013 {
2014 if (*lockState)
2015 {
2016 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2017 FirmwareProvisioningStatus::ProvisionedAndLocked;
2018 }
2019 else
2020 {
2021 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2022 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2023 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302024 }
2025 else
2026 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002027 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002028 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302029 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002030 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302031}
AppaRao Pulia6349912019-10-18 17:16:08 +05302032
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302033/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002034 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002035 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002036 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002037 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002038 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002039 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002040inline computer_system::PowerMode translatePowerModeString(
2041 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002042{
Chris Cainb6655102024-02-01 14:35:33 -06002043 using PowerMode = computer_system::PowerMode;
2044
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002045 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002046 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002047 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002048 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002049 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002050 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002051 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002052 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002053 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002054 if (modeString ==
2055 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002056 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002057 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002058 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002059 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002060 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2061 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002062 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002063 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002064 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002065 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2066 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002067 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002068 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002069 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002070 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2071 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002072 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002073 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002074 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002075 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002076 return PowerMode::OEM;
2077 }
2078 // Any other values would be invalid
2079 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2080 return PowerMode::Invalid;
2081}
2082
Patrick Williams504af5a2025-02-03 14:29:03 -05002083inline void afterGetPowerMode(
2084 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2085 const boost::system::error_code& ec,
2086 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002087{
2088 if (ec)
2089 {
2090 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2091 messages::internalError(asyncResp->res);
2092 return;
2093 }
2094
2095 std::string powerMode;
2096 const std::vector<std::string>* allowedModes = nullptr;
2097 const bool success = sdbusplus::unpackPropertiesNoThrow(
2098 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2099 "AllowedPowerModes", allowedModes);
2100
2101 if (!success)
2102 {
2103 messages::internalError(asyncResp->res);
2104 return;
2105 }
2106
2107 nlohmann::json::array_t modeList;
2108 if (allowedModes == nullptr)
2109 {
2110 modeList.emplace_back("Static");
2111 modeList.emplace_back("MaximumPerformance");
2112 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002113 }
2114 else
2115 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002116 for (const auto& aMode : *allowedModes)
2117 {
2118 computer_system::PowerMode modeValue =
2119 translatePowerModeString(aMode);
2120 if (modeValue == computer_system::PowerMode::Invalid)
2121 {
2122 messages::internalError(asyncResp->res);
2123 continue;
2124 }
2125 modeList.emplace_back(modeValue);
2126 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002127 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002128 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002129
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002130 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2131 const computer_system::PowerMode modeValue =
2132 translatePowerModeString(powerMode);
2133 if (modeValue == computer_system::PowerMode::Invalid)
2134 {
2135 messages::internalError(asyncResp->res);
2136 return;
2137 }
2138 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2139}
Chris Cain3a2d04242021-05-28 16:57:10 -05002140/**
2141 * @brief Retrieves system power mode
2142 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002143 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002144 *
2145 * @return None.
2146 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002147inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002148{
Ed Tanous62598e32023-07-17 17:06:25 -07002149 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002150
2151 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002152 constexpr std::array<std::string_view, 1> interfaces = {
2153 "xyz.openbmc_project.Control.Power.Mode"};
2154 dbus::utility::getSubTree(
2155 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002156 [asyncResp](const boost::system::error_code& ec,
2157 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002158 if (ec)
2159 {
2160 BMCWEB_LOG_DEBUG(
2161 "DBUS response error on Power.Mode GetSubTree {}", ec);
2162 // This is an optional D-Bus object so just return if
2163 // error occurs
2164 return;
2165 }
2166 if (subtree.empty())
2167 {
2168 // As noted above, this is an optional interface so just return
2169 // if there is no instance found
2170 return;
2171 }
2172 if (subtree.size() > 1)
2173 {
2174 // More then one PowerMode object is not supported and is an
2175 // error
2176 BMCWEB_LOG_DEBUG(
2177 "Found more than 1 system D-Bus Power.Mode objects: {}",
2178 subtree.size());
2179 messages::internalError(asyncResp->res);
2180 return;
2181 }
2182 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2183 {
2184 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2185 messages::internalError(asyncResp->res);
2186 return;
2187 }
2188 const std::string& path = subtree[0].first;
2189 const std::string& service = subtree[0].second.begin()->first;
2190 if (service.empty())
2191 {
2192 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2193 messages::internalError(asyncResp->res);
2194 return;
2195 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002196
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002197 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002198 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002199 *crow::connections::systemBus, service, path,
2200 "xyz.openbmc_project.Control.Power.Mode",
2201 [asyncResp](
2202 const boost::system::error_code& ec2,
2203 const dbus::utility::DBusPropertiesMap& properties) {
2204 afterGetPowerMode(asyncResp, ec2, properties);
2205 });
George Liue99073f2022-12-09 11:06:16 +08002206 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002207}
2208
2209/**
2210 * @brief Validate the specified mode is valid and return the PowerMode
2211 * name associated with that string
2212 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002213 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002214 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002215 *
2216 * @return PowerMode value or empty string if mode is not valid
2217 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002218inline std::string validatePowerMode(
2219 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2220 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002221{
Chris Cainb6655102024-02-01 14:35:33 -06002222 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002223 std::string mode;
2224
Chris Cainb6655102024-02-01 14:35:33 -06002225 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002226 {
2227 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2228 }
Chris Cainb6655102024-02-01 14:35:33 -06002229 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002230 {
George Liu0fda0f12021-11-16 10:06:17 +08002231 mode =
2232 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002233 }
Chris Cainb6655102024-02-01 14:35:33 -06002234 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002235 {
2236 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2237 }
Chris Cainb6655102024-02-01 14:35:33 -06002238 else if (modeValue == PowerMode::BalancedPerformance)
2239 {
2240 mode =
2241 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2242 }
2243 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2244 {
2245 mode =
2246 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2247 }
2248 else if (modeValue == PowerMode::EfficiencyFavorPower)
2249 {
2250 mode =
2251 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2252 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002253 else
2254 {
Chris Cainb6655102024-02-01 14:35:33 -06002255 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002256 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002257 }
2258 return mode;
2259}
2260
2261/**
2262 * @brief Sets system power mode.
2263 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002264 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002265 * @param[in] pmode System power mode from request.
2266 *
2267 * @return None.
2268 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002269inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002270 const std::string& pmode)
2271{
Ed Tanous62598e32023-07-17 17:06:25 -07002272 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002273
Ed Tanousac106bf2023-06-07 09:24:59 -07002274 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002275 if (powerMode.empty())
2276 {
2277 return;
2278 }
2279
2280 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002281 constexpr std::array<std::string_view, 1> interfaces = {
2282 "xyz.openbmc_project.Control.Power.Mode"};
2283 dbus::utility::getSubTree(
2284 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002285 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002286 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002287 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002288 if (ec)
2289 {
2290 BMCWEB_LOG_ERROR(
2291 "DBUS response error on Power.Mode GetSubTree {}", ec);
2292 // This is an optional D-Bus object, but user attempted to patch
2293 messages::internalError(asyncResp->res);
2294 return;
2295 }
2296 if (subtree.empty())
2297 {
2298 // This is an optional D-Bus object, but user attempted to patch
2299 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2300 "PowerMode");
2301 return;
2302 }
2303 if (subtree.size() > 1)
2304 {
2305 // More then one PowerMode object is not supported and is an
2306 // error
2307 BMCWEB_LOG_DEBUG(
2308 "Found more than 1 system D-Bus Power.Mode objects: {}",
2309 subtree.size());
2310 messages::internalError(asyncResp->res);
2311 return;
2312 }
2313 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2314 {
2315 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2316 messages::internalError(asyncResp->res);
2317 return;
2318 }
2319 const std::string& path = subtree[0].first;
2320 const std::string& service = subtree[0].second.begin()->first;
2321 if (service.empty())
2322 {
2323 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2324 messages::internalError(asyncResp->res);
2325 return;
2326 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002327
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002328 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002329
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002330 // Set the Power Mode property
2331 setDbusProperty(asyncResp, "PowerMode", service, path,
2332 "xyz.openbmc_project.Control.Power.Mode",
2333 "PowerMode", powerMode);
2334 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002335}
2336
2337/**
Yong Li51709ff2019-09-30 14:13:04 +08002338 * @brief Translates watchdog timeout action DBUS property value to redfish.
2339 *
2340 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2341 *
2342 * @return Returns as a string, the timeout action in Redfish terms. If
2343 * translation cannot be done, returns an empty string.
2344 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002345inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002346{
2347 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2348 {
2349 return "None";
2350 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002351 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002352 {
2353 return "ResetSystem";
2354 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002355 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002356 {
2357 return "PowerDown";
2358 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002359 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002360 {
2361 return "PowerCycle";
2362 }
2363
2364 return "";
2365}
2366
2367/**
Yong Lic45f0082019-10-10 14:19:01 +08002368 *@brief Translates timeout action from Redfish to DBUS property value.
2369 *
2370 *@param[in] rfAction The timeout action in Redfish.
2371 *
2372 *@return Returns as a string, the time_out action as expected by DBUS.
2373 *If translation cannot be done, returns an empty string.
2374 */
2375
Ed Tanous23a21a12020-07-25 04:45:05 +00002376inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002377{
2378 if (rfAction == "None")
2379 {
2380 return "xyz.openbmc_project.State.Watchdog.Action.None";
2381 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002382 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002383 {
2384 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2385 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002386 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002387 {
2388 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2389 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002390 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002391 {
2392 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2393 }
2394
2395 return "";
2396}
2397
2398/**
Yong Li51709ff2019-09-30 14:13:04 +08002399 * @brief Retrieves host watchdog timer properties over DBUS
2400 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002401 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002402 *
2403 * @return None.
2404 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002405inline void getHostWatchdogTimer(
2406 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002407{
Ed Tanous62598e32023-07-17 17:06:25 -07002408 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002409 dbus::utility::getAllProperties(
2410 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002411 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002412 [asyncResp](const boost::system::error_code& ec,
2413 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002414 if (ec)
2415 {
2416 // watchdog service is stopped
2417 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2418 return;
2419 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002420
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002421 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002422
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002423 nlohmann::json& hostWatchdogTimer =
2424 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002425
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002426 // watchdog service is running/enabled
2427 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002428
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002429 const bool* enabled = nullptr;
2430 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002431
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002432 const bool success = sdbusplus::unpackPropertiesNoThrow(
2433 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2434 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002435
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002436 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002437 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002438 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002439 return;
2440 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002441
2442 if (enabled != nullptr)
2443 {
2444 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2445 }
2446
2447 if (expireAction != nullptr)
2448 {
2449 std::string action = dbusToRfWatchdogAction(*expireAction);
2450 if (action.empty())
2451 {
2452 messages::internalError(asyncResp->res);
2453 return;
2454 }
2455 hostWatchdogTimer["TimeoutAction"] = action;
2456 }
2457 });
Yong Li51709ff2019-09-30 14:13:04 +08002458}
2459
2460/**
Yong Lic45f0082019-10-10 14:19:01 +08002461 * @brief Sets Host WatchDog Timer properties.
2462 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002463 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002464 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2465 * RF request.
2466 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2467 *
2468 * @return None.
2469 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002470inline void setWDTProperties(
2471 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2472 const std::optional<bool> wdtEnable,
2473 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002474{
Ed Tanous62598e32023-07-17 17:06:25 -07002475 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002476
2477 if (wdtTimeOutAction)
2478 {
2479 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2480 // check if TimeOut Action is Valid
2481 if (wdtTimeOutActStr.empty())
2482 {
Ed Tanous62598e32023-07-17 17:06:25 -07002483 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2484 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002485 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002486 "TimeoutAction");
2487 return;
2488 }
2489
Ginu Georgee93abac2024-06-14 17:35:27 +05302490 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2491 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002492 sdbusplus::message::object_path(
2493 "/xyz/openbmc_project/watchdog/host0"),
2494 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302495 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002496 }
2497
2498 if (wdtEnable)
2499 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302500 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2501 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002502 sdbusplus::message::object_path(
2503 "/xyz/openbmc_project/watchdog/host0"),
2504 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302505 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002506 }
2507}
2508
Chris Cain37bbf982021-09-20 10:53:09 -05002509/**
2510 * @brief Parse the Idle Power Saver properties into json
2511 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002512 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002513 * @param[in] properties IPS property data from DBus.
2514 *
2515 * @return true if successful
2516 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002517inline bool parseIpsProperties(
2518 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2519 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002520{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002521 const bool* enabled = nullptr;
2522 const uint8_t* enterUtilizationPercent = nullptr;
2523 const uint64_t* enterDwellTime = nullptr;
2524 const uint8_t* exitUtilizationPercent = nullptr;
2525 const uint64_t* exitDwellTime = nullptr;
2526
2527 const bool success = sdbusplus::unpackPropertiesNoThrow(
2528 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002529 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2530 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2531 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002532
2533 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002534 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002535 return false;
2536 }
2537
2538 if (enabled != nullptr)
2539 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002540 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002541 }
2542
2543 if (enterUtilizationPercent != nullptr)
2544 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002545 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002546 *enterUtilizationPercent;
2547 }
2548
2549 if (enterDwellTime != nullptr)
2550 {
2551 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002552 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002553 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2554 .count();
2555 }
2556
2557 if (exitUtilizationPercent != nullptr)
2558 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002559 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002560 *exitUtilizationPercent;
2561 }
2562
2563 if (exitDwellTime != nullptr)
2564 {
2565 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002566 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002567 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2568 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002569 }
2570
2571 return true;
2572}
2573
2574/**
2575 * @brief Retrieves host watchdog timer properties over DBUS
2576 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002577 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002578 *
2579 * @return None.
2580 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002581inline void getIdlePowerSaver(
2582 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002583{
Ed Tanous62598e32023-07-17 17:06:25 -07002584 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002585
2586 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002587 constexpr std::array<std::string_view, 1> interfaces = {
2588 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2589 dbus::utility::getSubTree(
2590 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002591 [asyncResp](const boost::system::error_code& ec,
2592 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002593 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002594 {
Ed Tanous62598e32023-07-17 17:06:25 -07002595 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002596 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2597 ec);
2598 messages::internalError(asyncResp->res);
2599 return;
2600 }
2601 if (subtree.empty())
2602 {
2603 // This is an optional interface so just return
2604 // if there is no instance found
2605 BMCWEB_LOG_DEBUG("No instances found");
2606 return;
2607 }
2608 if (subtree.size() > 1)
2609 {
2610 // More then one PowerIdlePowerSaver object is not supported and
2611 // is an error
2612 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2613 "Power.IdlePowerSaver objects: {}",
2614 subtree.size());
2615 messages::internalError(asyncResp->res);
2616 return;
2617 }
2618 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2619 {
2620 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2621 messages::internalError(asyncResp->res);
2622 return;
2623 }
2624 const std::string& path = subtree[0].first;
2625 const std::string& service = subtree[0].second.begin()->first;
2626 if (service.empty())
2627 {
2628 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002629 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002630 return;
2631 }
2632
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002633 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002634 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002635 *crow::connections::systemBus, service, path,
2636 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2637 [asyncResp](
2638 const boost::system::error_code& ec2,
2639 const dbus::utility::DBusPropertiesMap& properties) {
2640 if (ec2)
2641 {
2642 BMCWEB_LOG_ERROR(
2643 "DBUS response error on IdlePowerSaver GetAll: {}",
2644 ec2);
2645 messages::internalError(asyncResp->res);
2646 return;
2647 }
2648
2649 if (!parseIpsProperties(asyncResp, properties))
2650 {
2651 messages::internalError(asyncResp->res);
2652 return;
2653 }
2654 });
George Liue99073f2022-12-09 11:06:16 +08002655 });
Chris Cain37bbf982021-09-20 10:53:09 -05002656
Ed Tanous62598e32023-07-17 17:06:25 -07002657 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002658}
2659
2660/**
2661 * @brief Sets Idle Power Saver properties.
2662 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002663 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002664 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2665 * RF request.
2666 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2667 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2668 * before entering idle state.
2669 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2670 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2671 * before exiting idle state
2672 *
2673 * @return None.
2674 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002675inline void setIdlePowerSaver(
2676 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2677 const std::optional<bool> ipsEnable,
2678 const std::optional<uint8_t> ipsEnterUtil,
2679 const std::optional<uint64_t> ipsEnterTime,
2680 const std::optional<uint8_t> ipsExitUtil,
2681 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002682{
Ed Tanous62598e32023-07-17 17:06:25 -07002683 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002684
2685 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002686 constexpr std::array<std::string_view, 1> interfaces = {
2687 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2688 dbus::utility::getSubTree(
2689 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002690 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002691 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002692 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002693 if (ec)
2694 {
2695 BMCWEB_LOG_ERROR(
2696 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2697 ec);
2698 messages::internalError(asyncResp->res);
2699 return;
2700 }
2701 if (subtree.empty())
2702 {
2703 // This is an optional D-Bus object, but user attempted to patch
2704 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2705 "IdlePowerSaver");
2706 return;
2707 }
2708 if (subtree.size() > 1)
2709 {
2710 // More then one PowerIdlePowerSaver object is not supported and
2711 // is an error
2712 BMCWEB_LOG_DEBUG(
2713 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2714 subtree.size());
2715 messages::internalError(asyncResp->res);
2716 return;
2717 }
2718 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2719 {
2720 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2721 messages::internalError(asyncResp->res);
2722 return;
2723 }
2724 const std::string& path = subtree[0].first;
2725 const std::string& service = subtree[0].second.begin()->first;
2726 if (service.empty())
2727 {
2728 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2729 messages::internalError(asyncResp->res);
2730 return;
2731 }
Chris Cain37bbf982021-09-20 10:53:09 -05002732
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002733 // Valid Power IdlePowerSaver object found, now set any values that
2734 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002735
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002736 if (ipsEnable)
2737 {
2738 setDbusProperty(
2739 asyncResp, "IdlePowerSaver/Enabled", service, path,
2740 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2741 "Enabled", *ipsEnable);
2742 }
2743 if (ipsEnterUtil)
2744 {
2745 setDbusProperty(
2746 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2747 service, path,
2748 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2749 "EnterUtilizationPercent", *ipsEnterUtil);
2750 }
2751 if (ipsEnterTime)
2752 {
2753 // Convert from seconds into milliseconds for DBus
2754 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2755 setDbusProperty(
2756 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2757 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2758 "EnterDwellTime", timeMilliseconds);
2759 }
2760 if (ipsExitUtil)
2761 {
2762 setDbusProperty(
2763 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2764 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2765 "ExitUtilizationPercent", *ipsExitUtil);
2766 }
2767 if (ipsExitTime)
2768 {
2769 // Convert from seconds into milliseconds for DBus
2770 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2771 setDbusProperty(
2772 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2773 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2774 "ExitDwellTime", timeMilliseconds);
2775 }
2776 });
Chris Cain37bbf982021-09-20 10:53:09 -05002777
Ed Tanous62598e32023-07-17 17:06:25 -07002778 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002779}
2780
Ed Tanousc1e219d2023-06-07 10:34:33 -07002781inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002782 crow::App& app, const crow::Request& req,
2783 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2784{
2785 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2786 {
2787 return;
2788 }
2789 asyncResp->res.addHeader(
2790 boost::beast::http::field::link,
2791 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2792}
2793
Ed Tanousc1e219d2023-06-07 10:34:33 -07002794inline void handleComputerSystemCollectionGet(
2795 crow::App& app, const crow::Request& req,
2796 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2797{
2798 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2799 {
2800 return;
2801 }
2802
2803 asyncResp->res.addHeader(
2804 boost::beast::http::field::link,
2805 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2806 asyncResp->res.jsonValue["@odata.type"] =
2807 "#ComputerSystemCollection.ComputerSystemCollection";
2808 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2809 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2810
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002811 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002812}
2813
Yong Lic45f0082019-10-10 14:19:01 +08002814/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002815 * Function transceives data with dbus directly.
2816 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002817inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002818{
Patrick Williams89492a12023-05-10 07:51:34 -05002819 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2820 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2821 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002822 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002823 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002824
Ed Tanous177612a2025-02-14 15:16:09 -08002825 dbus::utility::async_method_call(
2826 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002827 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002828 if (ec)
2829 {
2830 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2831 messages::internalError(asyncResp->res);
2832 return;
2833 }
2834 messages::success(asyncResp->res);
2835 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002836 serviceName, objectPath, interfaceName, method);
2837}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002838
Ed Tanousc1e219d2023-06-07 10:34:33 -07002839inline void handleComputerSystemResetActionPost(
2840 crow::App& app, const crow::Request& req,
2841 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2842 const std::string& systemName)
2843{
2844 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2845 {
2846 return;
2847 }
Gunnar Millsdd7090e2024-07-30 15:23:05 -05002848
2849 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2850 {
2851 if (systemName == "hypervisor")
2852 {
2853 handleHypervisorSystemResetPost(req, asyncResp);
2854 return;
2855 }
2856 }
2857
Ed Tanous253f11b2024-05-16 09:38:31 -07002858 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002859 {
2860 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2861 systemName);
2862 return;
2863 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002864 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002865 {
2866 // Option currently returns no systems. TBD
2867 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2868 systemName);
2869 return;
2870 }
2871 std::string resetType;
2872 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2873 {
2874 return;
2875 }
2876
2877 // Get the command and host vs. chassis
2878 std::string command;
2879 bool hostCommand = true;
2880 if ((resetType == "On") || (resetType == "ForceOn"))
2881 {
2882 command = "xyz.openbmc_project.State.Host.Transition.On";
2883 hostCommand = true;
2884 }
2885 else if (resetType == "ForceOff")
2886 {
2887 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2888 hostCommand = false;
2889 }
2890 else if (resetType == "ForceRestart")
2891 {
2892 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2893 hostCommand = true;
2894 }
2895 else if (resetType == "GracefulShutdown")
2896 {
2897 command = "xyz.openbmc_project.State.Host.Transition.Off";
2898 hostCommand = true;
2899 }
2900 else if (resetType == "GracefulRestart")
2901 {
2902 command =
2903 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2904 hostCommand = true;
2905 }
2906 else if (resetType == "PowerCycle")
2907 {
2908 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2909 hostCommand = true;
2910 }
2911 else if (resetType == "Nmi")
2912 {
2913 doNMI(asyncResp);
2914 return;
2915 }
2916 else
2917 {
2918 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2919 return;
2920 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002921 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002922
2923 if (hostCommand)
2924 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302925 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002926 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302927 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002928 }
2929 else
2930 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302931 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08002932 statePath / "chassis0",
2933 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302934 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002935 }
2936}
2937
Ed Tanousc1e219d2023-06-07 10:34:33 -07002938inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002939 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002940 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2941 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002942{
2943 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2944 {
2945 return;
2946 }
2947
2948 asyncResp->res.addHeader(
2949 boost::beast::http::field::link,
2950 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2951}
2952
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002953inline void afterPortRequest(
2954 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2955 const boost::system::error_code& ec,
2956 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2957{
2958 if (ec)
2959 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002960 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002961 messages::internalError(asyncResp->res);
2962 return;
2963 }
2964 for (const auto& data : socketData)
2965 {
2966 const std::string& socketPath = get<0>(data);
2967 const std::string& protocolName = get<1>(data);
2968 bool isProtocolEnabled = get<2>(data);
2969 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2970 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2971 // need to retrieve port number for
2972 // obmc-console-ssh service
2973 if (protocolName == "SSH")
2974 {
2975 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002976 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002977 int portNumber) {
2978 if (ec1)
2979 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002980 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002981 messages::internalError(asyncResp->res);
2982 return;
2983 }
2984 nlohmann::json& dataJson1 =
2985 asyncResp->res.jsonValue["SerialConsole"];
2986 dataJson1[protocolName]["Port"] = portNumber;
2987 });
2988 }
2989 }
2990}
Ed Tanousc1e219d2023-06-07 10:34:33 -07002991
Patrick Williams504af5a2025-02-03 14:29:03 -05002992inline void handleComputerSystemGet(
2993 crow::App& app, const crow::Request& req,
2994 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2995 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002996{
Ed Tanousc1e219d2023-06-07 10:34:33 -07002997 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2998 {
2999 return;
3000 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003001
Ed Tanous25b54db2024-04-17 15:40:31 -07003002 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003003 {
3004 // Option currently returns no systems. TBD
3005 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3006 systemName);
3007 return;
3008 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003009
Gunnar Mills68896202024-08-21 11:34:20 -05003010 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003011 {
Gunnar Mills68896202024-08-21 11:34:20 -05003012 if (systemName == "hypervisor")
3013 {
3014 handleHypervisorSystemGet(asyncResp);
3015 return;
3016 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003017 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003018
Ed Tanous253f11b2024-05-16 09:38:31 -07003019 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003020 {
3021 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3022 systemName);
3023 return;
3024 }
3025 asyncResp->res.addHeader(
3026 boost::beast::http::field::link,
3027 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3028 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003029 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003030 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3031 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanous539d8c62024-06-19 14:38:27 -07003032 asyncResp->res.jsonValue["SystemType"] =
3033 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003034 asyncResp->res.jsonValue["Description"] = "Computer System";
3035 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003036 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003037 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003038 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3039 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003040
Ed Tanous253f11b2024-05-16 09:38:31 -07003041 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3042 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3043 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3044 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3045 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3046 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003047 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003048 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3049 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003050
Ed Tanousc1e219d2023-06-07 10:34:33 -07003051 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003052 boost::urls::format(
3053 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3054 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003055 asyncResp->res
3056 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003057 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3058 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003059
Ed Tanous253f11b2024-05-16 09:38:31 -07003060 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3061 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3062 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3063 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003064
Ed Tanousc1e219d2023-06-07 10:34:33 -07003065 nlohmann::json::array_t managedBy;
3066 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003067 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3068 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003069 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003070 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3071 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003072
Ed Tanousc1e219d2023-06-07 10:34:33 -07003073 // Fill in SerialConsole info
3074 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3075 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003076
Ed Tanousc1e219d2023-06-07 10:34:33 -07003077 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3078 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3079 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3080 "Press ~. to exit console";
3081 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3082 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003083
Ed Tanous25b54db2024-04-17 15:40:31 -07003084 if constexpr (BMCWEB_KVM)
3085 {
3086 // Fill in GraphicalConsole info
3087 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3088 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3089 4;
3090 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3091 nlohmann::json::array_t({"KVMIP"});
3092 }
James Feistb49ac872019-05-21 15:12:01 -07003093
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003094 getMainChassisId(
3095 asyncResp, [](const std::string& chassisId,
3096 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3097 nlohmann::json::array_t chassisArray;
3098 nlohmann::json& chassis = chassisArray.emplace_back();
3099 chassis["@odata.id"] =
3100 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3101 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3102 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003103
George Liu59a17e42022-10-08 09:27:47 +08003104 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003105 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3106 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003107 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003108 getHostState(asyncResp);
3109 getBootProperties(asyncResp);
3110 getBootProgress(asyncResp);
3111 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003112 pcie_util::getPCIeDeviceList(asyncResp,
3113 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003114 getHostWatchdogTimer(asyncResp);
3115 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003116 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003117 getAutomaticRetryPolicy(asyncResp);
3118 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003119 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3120 {
3121 getProvisioningStatus(asyncResp);
3122 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003123 getTrustedModuleRequiredToBoot(asyncResp);
3124 getPowerMode(asyncResp);
3125 getIdlePowerSaver(asyncResp);
3126}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003127
Ed Tanousc1e219d2023-06-07 10:34:33 -07003128inline void handleComputerSystemPatch(
3129 crow::App& app, const crow::Request& req,
3130 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3131 const std::string& systemName)
3132{
3133 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3134 {
3135 return;
3136 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003137 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003138 {
3139 // Option currently returns no systems. TBD
3140 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3141 systemName);
3142 return;
3143 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003144 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003145 {
3146 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3147 systemName);
3148 return;
3149 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003150
Ed Tanousc1e219d2023-06-07 10:34:33 -07003151 asyncResp->res.addHeader(
3152 boost::beast::http::field::link,
3153 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003154
Ed Tanousc1e219d2023-06-07 10:34:33 -07003155 std::optional<bool> locationIndicatorActive;
3156 std::optional<std::string> indicatorLed;
3157 std::optional<std::string> assetTag;
3158 std::optional<std::string> powerRestorePolicy;
3159 std::optional<std::string> powerMode;
3160 std::optional<bool> wdtEnable;
3161 std::optional<std::string> wdtTimeOutAction;
3162 std::optional<std::string> bootSource;
3163 std::optional<std::string> bootType;
3164 std::optional<std::string> bootEnable;
3165 std::optional<std::string> bootAutomaticRetry;
3166 std::optional<uint32_t> bootAutomaticRetryAttempts;
3167 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003168 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003169 std::optional<bool> ipsEnable;
3170 std::optional<uint8_t> ipsEnterUtil;
3171 std::optional<uint64_t> ipsEnterTime;
3172 std::optional<uint8_t> ipsExitUtil;
3173 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003174
Patrick Williams504af5a2025-02-03 14:29:03 -05003175 if (!json_util::readJsonPatch( //
3176 req, asyncResp->res, //
3177 "AssetTag", assetTag, //
3178 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts, //
3179 "Boot/AutomaticRetryConfig", bootAutomaticRetry, //
3180 "Boot/BootSourceOverrideEnabled", bootEnable, //
3181 "Boot/BootSourceOverrideMode", bootType, //
3182 "Boot/BootSourceOverrideTarget", bootSource, //
3183 "Boot/StopBootOnFault", stopBootOnFault, //
Myung Baeafc474a2024-10-09 00:53:29 -07003184 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired, //
Patrick Williams504af5a2025-02-03 14:29:03 -05003185 "HostWatchdogTimer/FunctionEnabled", wdtEnable, //
3186 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction, //
3187 "IdlePowerSaver/Enabled", ipsEnable, //
3188 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime, //
3189 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil, //
3190 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime, //
3191 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil, //
3192 "IndicatorLED", indicatorLed, //
3193 "LocationIndicatorActive", locationIndicatorActive, //
3194 "PowerMode", powerMode, //
3195 "PowerRestorePolicy", powerRestorePolicy //
Myung Baeafc474a2024-10-09 00:53:29 -07003196 ))
Ed Tanousab344222024-08-07 18:01:23 -07003197 {
3198 return;
3199 }
James Feistb49ac872019-05-21 15:12:01 -07003200
Ed Tanousc1e219d2023-06-07 10:34:33 -07003201 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003202
Ed Tanousc1e219d2023-06-07 10:34:33 -07003203 if (assetTag)
3204 {
3205 setAssetTag(asyncResp, *assetTag);
3206 }
James Feistb49ac872019-05-21 15:12:01 -07003207
Ed Tanousc1e219d2023-06-07 10:34:33 -07003208 if (wdtEnable || wdtTimeOutAction)
3209 {
3210 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3211 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003212
Ed Tanousc1e219d2023-06-07 10:34:33 -07003213 if (bootSource || bootType || bootEnable)
3214 {
3215 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3216 }
3217 if (bootAutomaticRetry)
3218 {
3219 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3220 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003221
Ed Tanousc1e219d2023-06-07 10:34:33 -07003222 if (bootAutomaticRetryAttempts)
3223 {
3224 setAutomaticRetryAttempts(asyncResp,
3225 bootAutomaticRetryAttempts.value());
3226 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003227
Ed Tanousc1e219d2023-06-07 10:34:33 -07003228 if (bootTrustedModuleRequired)
3229 {
3230 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3231 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003232
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003233 if (stopBootOnFault)
3234 {
3235 setStopBootOnFault(asyncResp, *stopBootOnFault);
3236 }
3237
Ed Tanousc1e219d2023-06-07 10:34:33 -07003238 if (locationIndicatorActive)
3239 {
George Liu59a17e42022-10-08 09:27:47 +08003240 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003241 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003242
Ed Tanousc1e219d2023-06-07 10:34:33 -07003243 // TODO (Gunnar): Remove IndicatorLED after enough time has
3244 // passed
3245 if (indicatorLed)
3246 {
3247 setIndicatorLedState(asyncResp, *indicatorLed);
3248 asyncResp->res.addHeader(boost::beast::http::field::warning,
3249 "299 - \"IndicatorLED is deprecated. Use "
3250 "LocationIndicatorActive instead.\"");
3251 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003252
Ed Tanousc1e219d2023-06-07 10:34:33 -07003253 if (powerRestorePolicy)
3254 {
3255 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3256 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003257
Ed Tanousc1e219d2023-06-07 10:34:33 -07003258 if (powerMode)
3259 {
3260 setPowerMode(asyncResp, *powerMode);
3261 }
Chris Cain37bbf982021-09-20 10:53:09 -05003262
Ed Tanousc1e219d2023-06-07 10:34:33 -07003263 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3264 {
3265 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3266 ipsExitUtil, ipsExitTime);
3267 }
3268}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303269
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003270inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003271 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003272 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003273 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003274{
3275 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3276 {
3277 return;
3278 }
3279 asyncResp->res.addHeader(
3280 boost::beast::http::field::link,
3281 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3282}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003283
3284/**
3285 * @brief Translates allowed host transitions to redfish string
3286 *
3287 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3288 * @param[out] allowableValues The translated host transition(s)
3289 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303290 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003291 * allowableValues. If translation not possible, does nothing to
3292 * allowableValues.
3293 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003294inline void dbusToRfAllowedHostTransitions(
3295 const std::string& dbusAllowedHostTran,
3296 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003297{
3298 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3299 {
3300 allowableValues.emplace_back(resource::ResetType::On);
3301 allowableValues.emplace_back(resource::ResetType::ForceOn);
3302 }
3303 else if (dbusAllowedHostTran ==
3304 "xyz.openbmc_project.State.Host.Transition.Off")
3305 {
3306 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3307 }
3308 else if (dbusAllowedHostTran ==
3309 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3310 {
3311 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3312 }
3313 else if (dbusAllowedHostTran ==
3314 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3315 {
3316 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3317 }
3318 else
3319 {
3320 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3321 }
3322}
3323
3324inline void afterGetAllowedHostTransitions(
3325 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3326 const boost::system::error_code& ec,
3327 const std::vector<std::string>& allowedHostTransitions)
3328{
3329 nlohmann::json::array_t allowableValues;
3330
3331 // Supported on all systems currently
3332 allowableValues.emplace_back(resource::ResetType::ForceOff);
3333 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3334 allowableValues.emplace_back(resource::ResetType::Nmi);
3335
3336 if (ec)
3337 {
Ed Tanouse715d142024-03-07 15:47:37 -08003338 if ((ec.value() ==
3339 boost::system::linux_error::bad_request_descriptor) ||
3340 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003341 {
3342 // Property not implemented so just return defaults
3343 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3344 allowableValues.emplace_back(resource::ResetType::On);
3345 allowableValues.emplace_back(resource::ResetType::ForceOn);
3346 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3347 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3348 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3349 }
3350 else
3351 {
3352 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3353 messages::internalError(asyncResp->res);
3354 return;
3355 }
3356 }
3357 else
3358 {
3359 for (const std::string& transition : allowedHostTransitions)
3360 {
3361 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3362 dbusToRfAllowedHostTransitions(transition, allowableValues);
3363 }
3364 }
3365
3366 nlohmann::json::object_t parameter;
3367 parameter["Name"] = "ResetType";
3368 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003369 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003370 parameter["AllowableValues"] = std::move(allowableValues);
3371 nlohmann::json::array_t parameters;
3372 parameters.emplace_back(std::move(parameter));
3373 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3374}
3375
Ed Tanousc1e219d2023-06-07 10:34:33 -07003376inline void handleSystemCollectionResetActionGet(
3377 crow::App& app, const crow::Request& req,
3378 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3379 const std::string& systemName)
3380{
3381 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3382 {
3383 return;
3384 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003385 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003386 {
3387 // Option currently returns no systems. TBD
3388 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3389 systemName);
3390 return;
3391 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003392
Gunnar Mills68896202024-08-21 11:34:20 -05003393 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003394 {
Gunnar Mills68896202024-08-21 11:34:20 -05003395 if (systemName == "hypervisor")
3396 {
3397 handleHypervisorResetActionGet(asyncResp);
3398 return;
3399 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003400 }
3401
Ed Tanous253f11b2024-05-16 09:38:31 -07003402 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003403 {
3404 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3405 systemName);
3406 return;
3407 }
3408
3409 asyncResp->res.addHeader(
3410 boost::beast::http::field::link,
3411 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3412
3413 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003414 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3415 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003416 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3417 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3418 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3419
Andrew Geissler33e1f122024-02-26 21:10:16 -06003420 // Look to see if system defines AllowedHostTransitions
Ed Tanousdeae6a72024-11-11 21:58:57 -08003421 dbus::utility::getProperty<std::vector<std::string>>(
3422 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
3423 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
Andrew Geissler33e1f122024-02-26 21:10:16 -06003424 [asyncResp](const boost::system::error_code& ec,
3425 const std::vector<std::string>& allowedHostTransitions) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003426 afterGetAllowedHostTransitions(asyncResp, ec,
3427 allowedHostTransitions);
3428 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003429}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303430/**
3431 * SystemResetActionInfo derived class for delivering Computer Systems
3432 * ResetType AllowableValues using ResetInfo schema.
3433 */
Ed Tanous100afe52023-06-07 13:30:46 -07003434inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303435{
Ed Tanous100afe52023-06-07 13:30:46 -07003436 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3437 .privileges(redfish::privileges::headComputerSystemCollection)
3438 .methods(boost::beast::http::verb::head)(
3439 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3440
3441 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3442 .privileges(redfish::privileges::getComputerSystemCollection)
3443 .methods(boost::beast::http::verb::get)(
3444 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3445
3446 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3447 .privileges(redfish::privileges::headComputerSystem)
3448 .methods(boost::beast::http::verb::head)(
3449 std::bind_front(handleComputerSystemHead, std::ref(app)));
3450
3451 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3452 .privileges(redfish::privileges::getComputerSystem)
3453 .methods(boost::beast::http::verb::get)(
3454 std::bind_front(handleComputerSystemGet, std::ref(app)));
3455
3456 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3457 .privileges(redfish::privileges::patchComputerSystem)
3458 .methods(boost::beast::http::verb::patch)(
3459 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3460
3461 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3462 .privileges(redfish::privileges::postComputerSystem)
3463 .methods(boost::beast::http::verb::post)(std::bind_front(
3464 handleComputerSystemResetActionPost, std::ref(app)));
3465
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003466 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003467 .privileges(redfish::privileges::headActionInfo)
3468 .methods(boost::beast::http::verb::head)(std::bind_front(
3469 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003470 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003471 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003472 .methods(boost::beast::http::verb::get)(std::bind_front(
3473 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003474}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003475} // namespace redfish