blob: fd03018a371c20e1834e760f76bad83bdb0e3d7e [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02004#pragma once
5
Willy Tu13451e32023-05-24 16:08:18 -07006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070010#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070013#include "generated/enums/action_info.hpp"
Ed Tanous8d69c662023-06-21 10:29:06 -070014#include "generated/enums/computer_system.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070015#include "generated/enums/open_bmc_computer_system.hpp"
Andrew Geissler33e1f122024-02-26 21:10:16 -060016#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080017#include "http_request.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060018#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "logging.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070021#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "registries/privilege_registry.hpp"
24#include "utils/dbus_utils.hpp"
25#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050026#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080027#include "utils/sw_utils.hpp"
Oliver Brewkafc5ae942024-08-12 15:04:41 +020028#include "utils/systems_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070029#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080030
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <asm-generic/errno.h>
32
Andrew Geisslerfc903b32023-05-31 14:15:42 -040033#include <boost/asio/error.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <boost/beast/http/field.hpp>
35#include <boost/beast/http/status.hpp>
36#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080037#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060038#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070039#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080040#include <nlohmann/json.hpp>
41#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020042#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050043
George Liu7a1dbc42022-12-07 16:03:22 +080044#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080045#include <chrono>
46#include <cstddef>
47#include <cstdint>
48#include <functional>
Andrew Geissler33e1f122024-02-26 21:10:16 -060049#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080050#include <optional>
51#include <ratio>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060052#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080053#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080054#include <tuple>
Ed Tanous20fa6a22024-05-20 18:02:58 -070055#include <utility>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060056#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020057
Ed Tanous1abe55e2018-09-05 08:30:59 -070058namespace redfish
59{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020060
Abhishek Patel5c3e9272021-06-24 10:11:33 -050061const static std::array<std::pair<std::string_view, std::string_view>, 2>
62 protocolToDBusForSystems{
63 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
64
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065/**
66 * @brief Updates the Functional State of DIMMs
67 *
Ed Tanousac106bf2023-06-07 09:24:59 -070068 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050069 * @param[in] dimmState Dimm's Functional state, true/false
70 *
71 * @return None.
72 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040073inline void updateDimmProperties(
74 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050075{
Ed Tanous62598e32023-07-17 17:06:25 -070076 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050077
Gunnar Mills4e0453b2020-07-08 14:00:30 -050078 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050079 // Update STATE only if previous State was DISABLED and current Dimm is
80 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070081 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070082 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050083 if (prevMemSummary == "Disabled")
84 {
Ed Tanouse05aec52022-01-25 10:28:56 -080085 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050086 {
Ed Tanousac106bf2023-06-07 09:24:59 -070087 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050088 "Enabled";
89 }
90 }
91}
92
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050094 * @brief Update "ProcessorSummary" "Status" "State" based on
95 * CPU Functional State
96 *
Ed Tanousac106bf2023-06-07 09:24:59 -070097 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050098 * @param[in] cpuFunctionalState is CPU functional true/false
99 *
100 * @return None.
101 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700102inline void modifyCpuFunctionalState(
103 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500104{
Ed Tanous62598e32023-07-17 17:06:25 -0700105 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106
Ed Tanous02cad962022-06-30 16:50:15 -0700107 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700108 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500109
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500110 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500111 // Update STATE only if previous State was Non_Functional and current CPU is
112 // Functional.
113 if (prevProcState == "Disabled")
114 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800115 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500116 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700117 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 "Enabled";
119 }
120 }
121}
122
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500123/*
124 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
125 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700126 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500127 * @param[in] cpuPresenceState CPU present or not
128 *
129 * @return None.
130 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400131inline void modifyCpuPresenceState(
132 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuPresent)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500133{
Ed Tanous62598e32023-07-17 17:06:25 -0700134 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500135
136 if (isCpuPresent)
137 {
138 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700139 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500140 auto* procCountPtr =
141 procCount.get_ptr<nlohmann::json::number_integer_t*>();
142 if (procCountPtr != nullptr)
143 {
144 // shouldn't be possible to be nullptr
145 *procCountPtr += 1;
146 }
147 }
148}
149
Ali Ahmed382d6472021-09-03 16:53:53 -0500150inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700151 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500152 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
153 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500154{
Ed Tanous62598e32023-07-17 17:06:25 -0700155 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500156
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200157 // TODO: Get Model
158
159 const uint16_t* coreCount = nullptr;
160
161 const bool success = sdbusplus::unpackPropertiesNoThrow(
162 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
163
164 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700166 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200167 return;
168 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500169
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200170 if (coreCount != nullptr)
171 {
172 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700173 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200174 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500175
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200176 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500177 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200178 coreCountJson = *coreCount;
179 }
180 else
181 {
182 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500183 }
184 }
185}
186
187/*
188 * @brief Get ProcessorSummary fields
189 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700190 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500191 * @param[in] service dbus service for Cpu Information
192 * @param[in] path dbus path for Cpu
193 *
194 * @return None.
195 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500196inline void getProcessorSummary(
197 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
198 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500199{
Ed Tanousac106bf2023-06-07 09:24:59 -0700200 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
201 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500202 if (ec3)
203 {
Ed Tanous62598e32023-07-17 17:06:25 -0700204 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500205 return;
206 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700207 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500208 };
209
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500210 // Get the Presence of CPU
Ed Tanousdeae6a72024-11-11 21:58:57 -0800211 dbus::utility::getProperty<bool>(*crow::connections::systemBus, service,
212 path, "xyz.openbmc_project.Inventory.Item",
213 "Present", std::move(getCpuPresenceState));
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500214
Ed Tanousdeae6a72024-11-11 21:58:57 -0800215 dbus::utility::getAllProperties(
216 service, path, "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700217 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800218 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800219 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400220 if (ec2)
221 {
222 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
223 messages::internalError(asyncResp->res);
224 return;
225 }
226 getProcessorProperties(asyncResp, properties);
227 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500228}
229
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500230/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500231 * @brief processMemoryProperties fields
232 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700233 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500234 * @param[in] DBUS properties for memory
235 *
236 * @return None.
237 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500238inline void processMemoryProperties(
239 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
240 const dbus::utility::DBusPropertiesMap& properties)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500241{
Ed Tanous62598e32023-07-17 17:06:25 -0700242 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500243
244 if (properties.empty())
245 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500246 return;
247 }
248
249 const size_t* memorySizeInKB = nullptr;
250
251 const bool success = sdbusplus::unpackPropertiesNoThrow(
252 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
253 memorySizeInKB);
254
255 if (!success)
256 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700257 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500258 return;
259 }
260
261 if (memorySizeInKB != nullptr)
262 {
263 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700264 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500265 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500266 if (preValue == nullptr)
267 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700268 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500269 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500270 }
271 else
272 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700273 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500274 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
275 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500276 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500277 }
278}
279
280/*
281 * @brief Get getMemorySummary fields
282 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700283 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500284 * @param[in] service dbus service for memory Information
285 * @param[in] path dbus path for memory
286 *
287 * @return None.
288 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500289inline void getMemorySummary(
290 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
291 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500292{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800293 dbus::utility::getAllProperties(
294 service, path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700295 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500296 path](const boost::system::error_code& ec2,
297 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400298 if (ec2)
299 {
300 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
301 messages::internalError(asyncResp->res);
302 return;
303 }
304 processMemoryProperties(asyncResp, properties);
305 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500306}
307
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500308inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
309 const boost::system::error_code& ec,
310 const dbus::utility::DBusPropertiesMap& properties)
311{
312 if (ec)
313 {
314 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
315 messages::internalError(asyncResp->res);
316 return;
317 }
318 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
319
320 const std::string* uUID = nullptr;
321
322 const bool success = sdbusplus::unpackPropertiesNoThrow(
323 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
324
325 if (!success)
326 {
327 messages::internalError(asyncResp->res);
328 return;
329 }
330
331 if (uUID != nullptr)
332 {
333 std::string valueStr = *uUID;
334 if (valueStr.size() == 32)
335 {
336 valueStr.insert(8, 1, '-');
337 valueStr.insert(13, 1, '-');
338 valueStr.insert(18, 1, '-');
339 valueStr.insert(23, 1, '-');
340 }
341 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
342 asyncResp->res.jsonValue["UUID"] = valueStr;
343 }
344}
345
Patrick Williams504af5a2025-02-03 14:29:03 -0500346inline void afterGetInventory(
347 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
348 const boost::system::error_code& ec,
349 const dbus::utility::DBusPropertiesMap& propertiesList)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500350{
351 if (ec)
352 {
353 // doesn't have to include this
354 // interface
355 return;
356 }
357 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
358
359 const std::string* partNumber = nullptr;
360 const std::string* serialNumber = nullptr;
361 const std::string* manufacturer = nullptr;
362 const std::string* model = nullptr;
363 const std::string* subModel = nullptr;
364
365 const bool success = sdbusplus::unpackPropertiesNoThrow(
366 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
367 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
368 "Model", model, "SubModel", subModel);
369
370 if (!success)
371 {
372 messages::internalError(asyncResp->res);
373 return;
374 }
375
376 if (partNumber != nullptr)
377 {
378 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
379 }
380
381 if (serialNumber != nullptr)
382 {
383 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
384 }
385
386 if (manufacturer != nullptr)
387 {
388 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
389 }
390
391 if (model != nullptr)
392 {
393 asyncResp->res.jsonValue["Model"] = *model;
394 }
395
396 if (subModel != nullptr)
397 {
398 asyncResp->res.jsonValue["SubModel"] = *subModel;
399 }
400
401 // Grab the bios version
402 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
403 "BiosVersion", false);
404}
405
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400406inline void afterGetAssetTag(
407 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
408 const boost::system::error_code& ec, const std::string& value)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500409{
410 if (ec)
411 {
412 // doesn't have to include this
413 // interface
414 return;
415 }
416
417 asyncResp->res.jsonValue["AssetTag"] = value;
418}
419
420inline void afterSystemGetSubTree(
421 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500422 const boost::system::error_code& ec,
423 const dbus::utility::MapperGetSubTreeResponse& subtree)
424{
425 if (ec)
426 {
427 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
428 messages::internalError(asyncResp->res);
429 return;
430 }
431 // Iterate over all retrieved ObjectPaths.
432 for (const std::pair<
433 std::string,
434 std::vector<std::pair<std::string, std::vector<std::string>>>>&
435 object : subtree)
436 {
437 const std::string& path = object.first;
438 BMCWEB_LOG_DEBUG("Got path: {}", path);
439 const std::vector<std::pair<std::string, std::vector<std::string>>>&
440 connectionNames = object.second;
441 if (connectionNames.empty())
442 {
443 continue;
444 }
445
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500446 // This is not system, so check if it's cpu, dimm, UUID or
447 // BiosVer
448 for (const auto& connection : connectionNames)
449 {
450 for (const auto& interfaceName : connection.second)
451 {
452 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
453 {
454 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
455
456 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500457 }
458 else if (interfaceName ==
459 "xyz.openbmc_project.Inventory.Item.Cpu")
460 {
461 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
462
463 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500464 }
465 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
466 {
467 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
468
Ed Tanousdeae6a72024-11-11 21:58:57 -0800469 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500470 *crow::connections::systemBus, connection.first, path,
471 "xyz.openbmc_project.Common.UUID",
472 [asyncResp](const boost::system::error_code& ec3,
473 const dbus::utility::DBusPropertiesMap&
474 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400475 afterGetUUID(asyncResp, ec3, properties);
476 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500477 }
478 else if (interfaceName ==
479 "xyz.openbmc_project.Inventory.Item.System")
480 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800481 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500482 *crow::connections::systemBus, connection.first, path,
483 "xyz.openbmc_project.Inventory.Decorator.Asset",
484 [asyncResp](const boost::system::error_code& ec3,
485 const dbus::utility::DBusPropertiesMap&
486 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400487 afterGetInventory(asyncResp, ec3, properties);
488 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500489
Ed Tanousdeae6a72024-11-11 21:58:57 -0800490 dbus::utility::getProperty<std::string>(
491 connection.first, path,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500492 "xyz.openbmc_project.Inventory.Decorator."
493 "AssetTag",
494 "AssetTag",
495 std::bind_front(afterGetAssetTag, asyncResp));
496 }
497 }
498 }
499 }
500}
501
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500502/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700503 * @brief Retrieves computer system properties over dbus
504 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700505 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700506 *
507 * @return None.
508 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500509inline void getComputerSystem(
510 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700511{
Ed Tanous62598e32023-07-17 17:06:25 -0700512 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800513 constexpr std::array<std::string_view, 5> interfaces = {
514 "xyz.openbmc_project.Inventory.Decorator.Asset",
515 "xyz.openbmc_project.Inventory.Item.Cpu",
516 "xyz.openbmc_project.Inventory.Item.Dimm",
517 "xyz.openbmc_project.Inventory.Item.System",
518 "xyz.openbmc_project.Common.UUID",
519 };
520 dbus::utility::getSubTree(
521 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500522 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700523}
524
525/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700526 * @brief Retrieves host state properties over dbus
527 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200529 * @param[in] computerSystemIndex Index associated with the requested system
Ed Tanous6c34de42018-08-29 13:37:36 -0700530 *
531 * @return None.
532 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200533inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
534 const uint64_t computerSystemIndex)
Ed Tanous6c34de42018-08-29 13:37:36 -0700535{
Ed Tanous62598e32023-07-17 17:06:25 -0700536 BMCWEB_LOG_DEBUG("Get host information.");
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200537
Ed Tanousdeae6a72024-11-11 21:58:57 -0800538 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200539 getHostStateServiceName(computerSystemIndex),
540 getHostStateObjectPath(computerSystemIndex),
Ed Tanousdeae6a72024-11-11 21:58:57 -0800541 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700542 [asyncResp](const boost::system::error_code& ec,
543 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400544 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700545 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400546 if (ec == boost::system::errc::host_unreachable)
547 {
548 // Service not available, no error, just don't return
549 // host state info
550 BMCWEB_LOG_DEBUG("Service not available {}", ec);
551 return;
552 }
553 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
554 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700555 return;
556 }
Ed Tanous66173382018-08-15 18:20:59 -0700557
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400558 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
559 // Verify Host State
560 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
561 {
562 asyncResp->res.jsonValue["PowerState"] =
563 resource::PowerState::On;
564 asyncResp->res.jsonValue["Status"]["State"] =
565 resource::State::Enabled;
566 }
567 else if (hostState ==
568 "xyz.openbmc_project.State.Host.HostState.Quiesced")
569 {
570 asyncResp->res.jsonValue["PowerState"] =
571 resource::PowerState::On;
572 asyncResp->res.jsonValue["Status"]["State"] =
573 resource::State::Quiesced;
574 }
575 else if (hostState ==
576 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
577 {
578 asyncResp->res.jsonValue["PowerState"] =
579 resource::PowerState::On;
580 asyncResp->res.jsonValue["Status"]["State"] =
581 resource::State::InTest;
582 }
583 else if (
584 hostState ==
585 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
586 {
587 asyncResp->res.jsonValue["PowerState"] =
588 resource::PowerState::PoweringOn;
589 asyncResp->res.jsonValue["Status"]["State"] =
590 resource::State::Starting;
591 }
592 else if (
593 hostState ==
594 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
595 {
596 asyncResp->res.jsonValue["PowerState"] =
597 resource::PowerState::PoweringOff;
598 asyncResp->res.jsonValue["Status"]["State"] =
599 resource::State::Disabled;
600 }
601 else
602 {
603 asyncResp->res.jsonValue["PowerState"] =
604 resource::PowerState::Off;
605 asyncResp->res.jsonValue["Status"]["State"] =
606 resource::State::Disabled;
607 }
608 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700609}
610
611/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500612 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530613 *
614 * @param[in] dbusSource The boot source in DBUS speak.
615 *
616 * @return Returns as a string, the boot source in Redfish terms. If translation
617 * cannot be done, returns an empty string.
618 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000619inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530620{
621 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
622 {
623 return "None";
624 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700625 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530626 {
627 return "Hdd";
628 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700629 if (dbusSource ==
630 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530631 {
632 return "Cd";
633 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700634 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530635 {
636 return "Pxe";
637 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700638 if (dbusSource ==
639 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700640 {
641 return "Usb";
642 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700643 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530644}
645
646/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300647 * @brief Translates boot type DBUS property value to redfish.
648 *
649 * @param[in] dbusType The boot type in DBUS speak.
650 *
651 * @return Returns as a string, the boot type in Redfish terms. If translation
652 * cannot be done, returns an empty string.
653 */
654inline std::string dbusToRfBootType(const std::string& dbusType)
655{
656 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
657 {
658 return "Legacy";
659 }
660 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
661 {
662 return "UEFI";
663 }
664 return "";
665}
666
667/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500668 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530669 *
670 * @param[in] dbusMode The boot mode in DBUS speak.
671 *
672 * @return Returns as a string, the boot mode in Redfish terms. If translation
673 * cannot be done, returns an empty string.
674 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000675inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530676{
677 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
678 {
679 return "None";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530682 {
683 return "Diags";
684 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700685 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686 {
687 return "BiosSetup";
688 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700689 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530690}
691
692/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600693 * @brief Translates boot progress DBUS property value to redfish.
694 *
695 * @param[in] dbusBootProgress The boot progress in DBUS speak.
696 *
697 * @return Returns as a string, the boot progress in Redfish terms. If
698 * translation cannot be done, returns "None".
699 */
700inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
701{
702 // Now convert the D-Bus BootProgress to the appropriate Redfish
703 // enum
704 std::string rfBpLastState = "None";
705 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
706 "ProgressStages.Unspecified")
707 {
708 rfBpLastState = "None";
709 }
710 else if (dbusBootProgress ==
711 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
712 "PrimaryProcInit")
713 {
714 rfBpLastState = "PrimaryProcessorInitializationStarted";
715 }
716 else if (dbusBootProgress ==
717 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
718 "BusInit")
719 {
720 rfBpLastState = "BusInitializationStarted";
721 }
722 else if (dbusBootProgress ==
723 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
724 "MemoryInit")
725 {
726 rfBpLastState = "MemoryInitializationStarted";
727 }
728 else if (dbusBootProgress ==
729 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
730 "SecondaryProcInit")
731 {
732 rfBpLastState = "SecondaryProcessorInitializationStarted";
733 }
734 else if (dbusBootProgress ==
735 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
736 "PCIInit")
737 {
738 rfBpLastState = "PCIResourceConfigStarted";
739 }
740 else if (dbusBootProgress ==
741 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
742 "SystemSetup")
743 {
744 rfBpLastState = "SetupEntered";
745 }
746 else if (dbusBootProgress ==
747 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
748 "SystemInitComplete")
749 {
750 rfBpLastState = "SystemHardwareInitializationComplete";
751 }
752 else if (dbusBootProgress ==
753 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
754 "OSStart")
755 {
756 rfBpLastState = "OSBootStarted";
757 }
758 else if (dbusBootProgress ==
759 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
760 "OSRunning")
761 {
762 rfBpLastState = "OSRunning";
763 }
764 else
765 {
Ed Tanous62598e32023-07-17 17:06:25 -0700766 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600767 // Just return the default
768 }
769 return rfBpLastState;
770}
771
772/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500773 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 *
775 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 * @param[out] bootSource The DBus source
777 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400781inline int assignBootParameters(
782 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
783 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300785 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
786 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788 if (rfSource == "None")
789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700792 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530793 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
795 }
796 else if (rfSource == "Hdd")
797 {
798 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
799 }
800 else if (rfSource == "Diags")
801 {
802 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
803 }
804 else if (rfSource == "Cd")
805 {
806 bootSource =
807 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
808 }
809 else if (rfSource == "BiosSetup")
810 {
811 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530812 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 else if (rfSource == "Usb")
814 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700815 bootSource =
816 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700817 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818 else
819 {
Ed Tanous62598e32023-07-17 17:06:25 -0700820 BMCWEB_LOG_DEBUG(
821 "Invalid property value for BootSourceOverrideTarget: {}",
822 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700823 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700824 "BootSourceTargetOverride");
825 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530826 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700827 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828}
Ali Ahmed19817712021-06-29 17:01:52 -0500829
Andrew Geissler978b8802020-11-19 13:36:40 -0600830/**
831 * @brief Retrieves boot progress of the system
832 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700833 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200834 * @param[in] computerSystemIndex Index associated with the requested system
Andrew Geissler978b8802020-11-19 13:36:40 -0600835 *
836 * @return None.
837 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200838inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
839 const uint64_t computerSystemIndex)
Andrew Geissler978b8802020-11-19 13:36:40 -0600840{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800841 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200842 getHostStateServiceName(computerSystemIndex),
843 getHostStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700844 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700845 [asyncResp](const boost::system::error_code& ec,
846 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400847 if (ec)
848 {
849 // BootProgress is an optional object so just do nothing if
850 // not found
851 return;
852 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600853
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400854 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600855
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400856 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
857 dbusToRfBootProgress(bootProgressStr);
858 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600859}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530860
861/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000862 * @brief Retrieves boot progress Last Update of the system
863 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700864 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200865 * @param[in] computerSystemIndex Index associated with the requested system
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000866 *
867 * @return None.
868 */
869inline void getBootProgressLastStateTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200870 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
871 const uint64_t computerSystemIndex)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000872{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800873 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200874 getHostStateServiceName(computerSystemIndex),
875 getHostStateObjectPath(computerSystemIndex),
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000876 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700877 [asyncResp](const boost::system::error_code& ec,
878 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400879 if (ec)
880 {
881 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
882 return;
883 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000884
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400885 // BootProgressLastUpdate is the last time the BootProgress property
886 // was updated. The time is the Epoch time, number of microseconds
887 // since 1 Jan 1970 00::00::00 UTC."
888 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
889 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000890
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400891 // Convert to ISO 8601 standard
892 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
893 redfish::time_utils::getDateTimeUintUs(lastStateTime);
894 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000895}
896
897/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300898 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300899 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700900 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200901 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300902 *
903 * @return None.
904 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500905inline void getBootOverrideType(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200906 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
907 const uint64_t computerSystemIndex)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300908{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200909 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
910 std::to_string(computerSystemIndex));
911 path /= "boot";
912
Ed Tanousdeae6a72024-11-11 21:58:57 -0800913 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200914 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700915 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700916 [asyncResp](const boost::system::error_code& ec,
917 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400918 if (ec)
919 {
920 // not an error, don't have to have the interface
921 return;
922 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400924 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300925
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400926 asyncResp->res
927 .jsonValue["Boot"]
928 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
929 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300930
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400931 auto rfType = dbusToRfBootType(bootType);
932 if (rfType.empty())
933 {
934 messages::internalError(asyncResp->res);
935 return;
936 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300937
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400938 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
939 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300940}
941
942/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700945 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200946 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530947 *
948 * @return None.
949 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500950inline void getBootOverrideMode(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200951 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
952 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530953{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200954 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
955 std::to_string(computerSystemIndex));
956 path /= "boot";
Ed Tanousdeae6a72024-11-11 21:58:57 -0800957 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200958 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700959 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700960 [asyncResp](const boost::system::error_code& ec,
961 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400962 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530963 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400964 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
965 messages::internalError(asyncResp->res);
966 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400968
969 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
970
971 nlohmann::json::array_t allowed;
972 allowed.emplace_back("None");
973 allowed.emplace_back("Pxe");
974 allowed.emplace_back("Hdd");
975 allowed.emplace_back("Cd");
976 allowed.emplace_back("Diags");
977 allowed.emplace_back("BiosSetup");
978 allowed.emplace_back("Usb");
979
980 asyncResp->res
981 .jsonValue["Boot"]
982 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
983 std::move(allowed);
984 if (bootModeStr !=
985 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
986 {
987 auto rfMode = dbusToRfBootMode(bootModeStr);
988 if (!rfMode.empty())
989 {
990 asyncResp->res
991 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
992 }
993 }
994 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530995}
996
997/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300998 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530999 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001000 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001001 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301002 *
1003 * @return None.
1004 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001005inline void getBootOverrideSource(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001006 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1007 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001009 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1010 std::to_string(computerSystemIndex));
1011 path /= "boot";
1012
Ed Tanousdeae6a72024-11-11 21:58:57 -08001013 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001014 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001015 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001016 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1017 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001018 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001019 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001020 // Service not available, no error, just don't return
1021 // Boot Override Source information
1022 if (ec.value() != EBADR &&
1023 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001024 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001025 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1026 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001027 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001028 return;
1029 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301030
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001031 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301032
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001033 auto rfSource = dbusToRfBootSource(bootSourceStr);
1034 if (!rfSource.empty())
1035 {
1036 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1037 rfSource;
1038 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001039
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001040 // Get BootMode as BootSourceOverrideTarget is constructed
1041 // from both BootSource and BootMode
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001042 getBootOverrideMode(asyncResp, computerSystemIndex);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001043 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044}
1045
1046/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001047 * @brief This functions abstracts all the logic behind getting a
1048 * "BootSourceOverrideEnabled" property from an overall boot override enable
1049 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301050 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001051 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001052 * @param[in] computerSystemIndex Index associated with the requested system
1053 * @param[in] bootOverrideEnableSetting
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301054 *
1055 * @return None.
1056 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301057
Ed Tanousac106bf2023-06-07 09:24:59 -07001058inline void processBootOverrideEnable(
1059 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001060 const uint64_t computerSystemIndex, const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001061{
1062 if (!bootOverrideEnableSetting)
1063 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001064 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1065 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001066 return;
1067 }
1068
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001069 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1070 std::to_string(computerSystemIndex));
1071 path /= "boot";
1072 path /= "one_time";
1073
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074 // If boot source override is enabled, we need to check 'one_time'
1075 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001076 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001077 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001078 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001079 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001080 if (ec)
1081 {
1082 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1083 messages::internalError(asyncResp->res);
1084 return;
1085 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301086
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001087 if (oneTimeSetting)
1088 {
1089 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1090 "Once";
1091 }
1092 else
1093 {
1094 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1095 "Continuous";
1096 }
1097 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301098}
1099
1100/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001101 * @brief Retrieves boot override enable over DBUS
1102 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001103 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001104 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001105 *
1106 * @return None.
1107 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001108inline void getBootOverrideEnable(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001109 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1110 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001111{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001112 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1113 std::to_string(computerSystemIndex));
1114 path /= "boot";
1115
Ed Tanousdeae6a72024-11-11 21:58:57 -08001116 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001117 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001118 "xyz.openbmc_project.Object.Enable", "Enabled",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001119 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1120 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001121 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001122 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001123 // Service not available, no error, just don't return
1124 // Boot Override Enable information
1125 if (ec.value() != EBADR &&
1126 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001127 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001128 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1129 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001130 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001131 return;
1132 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001133
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001134 processBootOverrideEnable(asyncResp, computerSystemIndex,
1135 bootOverrideEnable);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001136 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001137}
1138
1139/**
1140 * @brief Retrieves boot source override properties
1141 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001142 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001143 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001144 *
1145 * @return None.
1146 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001147inline void getBootProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001148 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1149 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001150{
Ed Tanous62598e32023-07-17 17:06:25 -07001151 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001152
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001153 getBootOverrideSource(asyncResp, computerSystemIndex);
1154 getBootOverrideType(asyncResp, computerSystemIndex);
1155 getBootOverrideEnable(asyncResp, computerSystemIndex);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001156}
1157
1158/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001159 * @brief Retrieves the Last Reset Time
1160 *
1161 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1162 * and power off. Even though this is the "system" Redfish object look at the
1163 * chassis D-Bus interface for the LastStateChangeTime since this has the
1164 * last power operation time.
1165 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001166 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001167 *
1168 * @return None.
1169 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001170inline void getLastResetTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1172 const uint64_t computerSystemIndex)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001173{
Ed Tanous62598e32023-07-17 17:06:25 -07001174 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001175
Ed Tanousdeae6a72024-11-11 21:58:57 -08001176 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001177 getChassisStateServiceName(computerSystemIndex),
1178 getChassisStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001179 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001180 [asyncResp](const boost::system::error_code& ec,
1181 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001182 if (ec)
1183 {
1184 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1185 return;
1186 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001187
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001188 // LastStateChangeTime is epoch time, in milliseconds
1189 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1190 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001191
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001192 // Convert to ISO 8601 standard
1193 asyncResp->res.jsonValue["LastResetTime"] =
1194 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1195 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001196}
1197
1198/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001199 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1200 *
1201 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1202 * corresponding property "AttemptsLeft" that keeps track of the amount of
1203 * automatic retry attempts left are hosted in phosphor-state-manager through
1204 * dbus.
1205 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001206 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001207 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001208 *
1209 * @return None.
1210 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001211inline void getAutomaticRebootAttempts(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001212 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1213 const uint64_t computerSystemIndex)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001214{
Ed Tanous62598e32023-07-17 17:06:25 -07001215 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001216
Ed Tanousdeae6a72024-11-11 21:58:57 -08001217 dbus::utility::getAllProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001218 getHostStateServiceName(computerSystemIndex),
1219 getHostStateObjectPath(computerSystemIndex),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001220 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001221 [asyncResp{asyncResp}](
1222 const boost::system::error_code& ec,
1223 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001224 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001225 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301226 if (ec.value() != EBADR &&
1227 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001228 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301229 // Service not available, no error, just don't return
1230 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001231 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1232 messages::internalError(asyncResp->res);
1233 }
1234 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001235 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001236
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001237 const uint32_t* attemptsLeft = nullptr;
1238 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001239
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001240 const bool success = sdbusplus::unpackPropertiesNoThrow(
1241 dbus_utils::UnpackErrorPrinter(), propertiesList,
1242 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001243
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001244 if (!success)
1245 {
1246 messages::internalError(asyncResp->res);
1247 return;
1248 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001249
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001250 if (attemptsLeft != nullptr)
1251 {
1252 asyncResp->res
1253 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1254 *attemptsLeft;
1255 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001256
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001257 if (retryAttempts != nullptr)
1258 {
1259 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1260 *retryAttempts;
1261 }
1262 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001263}
1264
1265/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001266 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1267 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001268 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001269 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001270 *
1271 * @return None.
1272 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001273inline void getAutomaticRetryPolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001274 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1275 const uint64_t computerSystemIndex)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001276{
Ed Tanous62598e32023-07-17 17:06:25 -07001277 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001278
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001279 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1280 std::to_string(computerSystemIndex));
1281 path /= "auto_reboot";
1282
Ed Tanousdeae6a72024-11-11 21:58:57 -08001283 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001284 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001285 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001286 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1287 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001288 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001289 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301290 // Service not available, no error, just don't return
1291 // AutoReboot information
1292 if (ec.value() != EBADR &&
1293 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001294 {
1295 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1296 messages::internalError(asyncResp->res);
1297 }
1298 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001299 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001300
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001301 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1302 if (autoRebootEnabled)
1303 {
1304 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1305 "RetryAttempts";
1306 }
1307 else
1308 {
1309 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1310 "Disabled";
1311 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001312 getAutomaticRebootAttempts(asyncResp, computerSystemIndex);
Gunnar Mills69f35302020-05-17 16:06:31 -05001313
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001314 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1315 // and RetryAttempts. OpenBMC only supports Disabled and
1316 // RetryAttempts.
1317 nlohmann::json::array_t allowed;
1318 allowed.emplace_back("Disabled");
1319 allowed.emplace_back("RetryAttempts");
1320 asyncResp->res
1321 .jsonValue["Boot"]
1322 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1323 std::move(allowed);
1324 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001325}
1326
1327/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001328 * @brief Sets RetryAttempts
1329 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001330 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001331 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001332 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1333 *
1334 *@return None.
1335 */
1336
Ed Tanousac106bf2023-06-07 09:24:59 -07001337inline void setAutomaticRetryAttempts(
1338 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1339 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001340{
Ed Tanous62598e32023-07-17 17:06:25 -07001341 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001342 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301343 asyncResp, "Boot/AutomaticRetryAttempts",
1344 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001345 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001346 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301347 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001348}
1349
Ed Tanous8d69c662023-06-21 10:29:06 -07001350inline computer_system::PowerRestorePolicyTypes
1351 redfishPowerRestorePolicyFromDbus(std::string_view value)
1352{
1353 if (value ==
1354 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1355 {
1356 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1357 }
1358 if (value ==
1359 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1360 {
1361 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1362 }
1363 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001364 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001365 {
1366 return computer_system::PowerRestorePolicyTypes::LastState;
1367 }
1368 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1369 {
1370 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1371 }
1372 return computer_system::PowerRestorePolicyTypes::Invalid;
1373}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001374/**
George Liuc6a620f2020-04-10 17:18:11 +08001375 * @brief Retrieves power restore policy over DBUS.
1376 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001377 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001378 *
1379 * @return None.
1380 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001381inline void getPowerRestorePolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001382 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1383 const uint64_t computerSystemIndex)
George Liuc6a620f2020-04-10 17:18:11 +08001384{
Ed Tanous62598e32023-07-17 17:06:25 -07001385 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001386
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001387 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1388 std::to_string(computerSystemIndex));
1389 path /= "power_restore_policy";
1390
Ed Tanousdeae6a72024-11-11 21:58:57 -08001391 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001392 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001393 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001394 [asyncResp](const boost::system::error_code& ec,
1395 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001396 if (ec)
1397 {
1398 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1399 return;
1400 }
1401 computer_system::PowerRestorePolicyTypes restore =
1402 redfishPowerRestorePolicyFromDbus(policy);
1403 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1404 {
1405 messages::internalError(asyncResp->res);
1406 return;
1407 }
George Liuc6a620f2020-04-10 17:18:11 +08001408
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001409 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1410 });
George Liuc6a620f2020-04-10 17:18:11 +08001411}
1412
1413/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001414 * @brief Stop Boot On Fault over DBUS.
1415 *
1416 * @param[in] asyncResp Shared pointer for generating response message.
1417 *
1418 * @return None.
1419 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001420inline void getStopBootOnFault(
1421 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001422{
Ed Tanous62598e32023-07-17 17:06:25 -07001423 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001424
Ed Tanousdeae6a72024-11-11 21:58:57 -08001425 dbus::utility::getProperty<bool>(
1426 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001427 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1428 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001429 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001430 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301431 // Service not available, no error, just don't return
1432 // StopBootOnFault information
1433 if (ec.value() != EBADR ||
1434 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001435 {
1436 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1437 messages::internalError(asyncResp->res);
1438 }
1439 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001440 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001441
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001442 if (value)
1443 {
1444 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1445 computer_system::StopBootOnFault::AnyFault;
1446 }
1447 else
1448 {
1449 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1450 computer_system::StopBootOnFault::Never;
1451 }
1452 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001453}
1454
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001455inline void getTrustedModuleRequiredToBootCallback(
1456 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1457 const uint64_t computerSystemIndex, const boost::system::error_code& ec,
1458 const dbus::utility::MapperGetSubTreeResponse& subtree)
1459{
1460 if (ec)
1461 {
1462 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}", ec);
1463 // This is an optional D-Bus object so just return if
1464 // error occurs
1465 return;
1466 }
1467 if (subtree.empty())
1468 {
1469 // As noted above, this is an optional interface so just return
1470 // if there is no instance found
1471 return;
1472 }
1473
1474 std::string path;
1475 std::string service;
1476
1477 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1478 {
1479 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1480 subtree, path, service))
1481 {
1482 return;
1483 }
1484 }
1485 else
1486 {
1487 // Make sure the Dbus response map has a service and objectPath
1488 // field
1489 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1490 {
1491 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1492 messages::internalError(asyncResp->res);
1493 return;
1494 }
1495
1496 path = subtree[0].first;
1497 service = subtree[0].second.begin()->first;
1498 }
1499
1500 BMCWEB_LOG_DEBUG("found tpm service {}", service);
1501 BMCWEB_LOG_DEBUG("found tpm path {}", path);
1502
1503 // Valid TPM Enable object found, now reading the current value
1504 dbus::utility::getProperty<bool>(
1505 service, path, "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1506 [asyncResp](const boost::system::error_code& ec2, bool tpmRequired) {
1507 if (ec2)
1508 {
1509 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
1510 ec2);
1511 messages::internalError(asyncResp->res);
1512 return;
1513 }
1514
1515 if (tpmRequired)
1516 {
1517 asyncResp->res
1518 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1519 "Required";
1520 }
1521 else
1522 {
1523 asyncResp->res
1524 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1525 "Disabled";
1526 }
1527 });
1528}
1529
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001530/**
Ali Ahmed19817712021-06-29 17:01:52 -05001531 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1532 * TPM is required for booting the host.
1533 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001534 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001535 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed19817712021-06-29 17:01:52 -05001536 *
1537 * @return None.
1538 */
1539inline void getTrustedModuleRequiredToBoot(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001540 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1541 const uint64_t computerSystemIndex)
Ali Ahmed19817712021-06-29 17:01:52 -05001542{
Ed Tanous62598e32023-07-17 17:06:25 -07001543 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001544 constexpr std::array<std::string_view, 1> interfaces = {
1545 "xyz.openbmc_project.Control.TPM.Policy"};
1546 dbus::utility::getSubTree(
1547 "/", 0, interfaces,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001548 std::bind_front(getTrustedModuleRequiredToBootCallback, asyncResp,
1549 computerSystemIndex));
Ali Ahmed19817712021-06-29 17:01:52 -05001550}
1551
1552/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001553 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1554 * TPM is required for booting the host.
1555 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001556 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001557 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1558 *
1559 * @return None.
1560 */
1561inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001562 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001563{
Ed Tanous62598e32023-07-17 17:06:25 -07001564 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001565 constexpr std::array<std::string_view, 1> interfaces = {
1566 "xyz.openbmc_project.Control.TPM.Policy"};
1567 dbus::utility::getSubTree(
1568 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001569 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001570 tpmRequired](const boost::system::error_code& ec,
1571 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001572 if (ec)
1573 {
1574 BMCWEB_LOG_ERROR(
1575 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1576 messages::internalError(asyncResp->res);
1577 return;
1578 }
1579 if (subtree.empty())
1580 {
1581 messages::propertyValueNotInList(asyncResp->res,
1582 "ComputerSystem",
1583 "TrustedModuleRequiredToBoot");
1584 return;
1585 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001586
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001587 /* When there is more than one TPMEnable object... */
1588 if (subtree.size() > 1)
1589 {
1590 BMCWEB_LOG_DEBUG(
1591 "DBUS response has more than 1 TPM Enable object:{}",
1592 subtree.size());
1593 // Throw an internal Error and return
1594 messages::internalError(asyncResp->res);
1595 return;
1596 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001597
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001598 // Make sure the Dbus response map has a service and objectPath
1599 // field
1600 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1601 {
1602 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1603 messages::internalError(asyncResp->res);
1604 return;
1605 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001606
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001607 const std::string& path = subtree[0].first;
1608 const std::string& serv = subtree[0].second.begin()->first;
Ed Tanous002d39b2022-05-31 08:59:27 -07001609
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001610 if (serv.empty())
1611 {
1612 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1613 messages::internalError(asyncResp->res);
1614 return;
1615 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001616
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001617 // Valid TPM Enable object found, now setting the value
1618 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1619 path, "xyz.openbmc_project.Control.TPM.Policy",
1620 "TPMEnable", tpmRequired);
1621 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001622}
1623
1624/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301625 * @brief Sets boot properties into DBUS object(s).
1626 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001627 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001628 * @param[in] bootType The boot type to set.
1629 * @return Integer error code.
1630 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001631inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001632 const std::optional<std::string>& bootType)
1633{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001634 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001635
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001636 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001637 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001638 return;
1639 }
1640
1641 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001642 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001643 // Figure out which DBUS interface and property to use
1644 if (*bootType == "Legacy")
1645 {
1646 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1647 }
1648 else if (*bootType == "UEFI")
1649 {
1650 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1651 }
1652 else
1653 {
Ed Tanous62598e32023-07-17 17:06:25 -07001654 BMCWEB_LOG_DEBUG("Invalid property value for "
1655 "BootSourceOverrideMode: {}",
1656 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001657 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001658 "BootSourceOverrideMode");
1659 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001660 }
1661
1662 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001663 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001664
Ginu Georgee93abac2024-06-14 17:35:27 +05301665 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1666 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001667 sdbusplus::message::object_path(
1668 "/xyz/openbmc_project/control/host0/boot"),
1669 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301670 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001671}
1672
1673/**
1674 * @brief Sets boot properties into DBUS object(s).
1675 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001676 * @param[in] asyncResp Shared pointer for generating response
1677 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001678 * @param[in] bootType The boot type to set.
1679 * @return Integer error code.
1680 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001681inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001682 const std::optional<std::string>& bootEnable)
1683{
1684 if (!bootEnable)
1685 {
1686 return;
1687 }
1688 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001689 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690
1691 bool bootOverrideEnable = false;
1692 bool bootOverridePersistent = false;
1693 // Figure out which DBUS interface and property to use
1694 if (*bootEnable == "Disabled")
1695 {
1696 bootOverrideEnable = false;
1697 }
1698 else if (*bootEnable == "Once")
1699 {
1700 bootOverrideEnable = true;
1701 bootOverridePersistent = false;
1702 }
1703 else if (*bootEnable == "Continuous")
1704 {
1705 bootOverrideEnable = true;
1706 bootOverridePersistent = true;
1707 }
1708 else
1709 {
Ed Tanous62598e32023-07-17 17:06:25 -07001710 BMCWEB_LOG_DEBUG(
1711 "Invalid property value for BootSourceOverrideEnabled: {}",
1712 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001713 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001714 "BootSourceOverrideEnabled");
1715 return;
1716 }
1717
1718 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001719 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001720
Ginu Georgee93abac2024-06-14 17:35:27 +05301721 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1722 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001723 sdbusplus::message::object_path(
1724 "/xyz/openbmc_project/control/host0/boot"),
1725 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301726 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001727
1728 if (!bootOverrideEnable)
1729 {
1730 return;
1731 }
1732
1733 // In case boot override is enabled we need to set correct value for the
1734 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001735 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1736 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001737
Ginu Georgee93abac2024-06-14 17:35:27 +05301738 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1739 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001740 sdbusplus::message::object_path(
1741 "/xyz/openbmc_project/control/host0/boot/one_time"),
1742 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301743 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001744}
1745
1746/**
1747 * @brief Sets boot properties into DBUS object(s).
1748 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001749 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301750 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301751 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001752 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301753 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001754inline void setBootModeOrSource(
1755 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1756 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301757{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001758 std::string bootSourceStr;
1759 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001760
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001761 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301762 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001763 return;
1764 }
1765
1766 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001767 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001768 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001769 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1770 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001771 {
Ed Tanous62598e32023-07-17 17:06:25 -07001772 BMCWEB_LOG_DEBUG(
1773 "Invalid property value for BootSourceOverrideTarget: {}",
1774 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001775 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001776 "BootSourceTargetOverride");
1777 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001778 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301779
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001780 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001781 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1782 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001783
Ginu Georgee93abac2024-06-14 17:35:27 +05301784 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1785 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001786 sdbusplus::message::object_path(
1787 "/xyz/openbmc_project/control/host0/boot"),
1788 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301789 bootSourceStr);
1790 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1791 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001792 sdbusplus::message::object_path(
1793 "/xyz/openbmc_project/control/host0/boot"),
1794 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301795 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001796}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001797
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001798/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001799 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301800 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001801 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301802 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001803 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301804 * @param[in] bootEnable The boot override enable from incoming RF request.
1805 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001806 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301807 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001808
Patrick Williams504af5a2025-02-03 14:29:03 -05001809inline void setBootProperties(
1810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1811 const std::optional<std::string>& bootSource,
1812 const std::optional<std::string>& bootType,
1813 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301814{
Ed Tanous62598e32023-07-17 17:06:25 -07001815 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301816
Ed Tanousac106bf2023-06-07 09:24:59 -07001817 setBootModeOrSource(asyncResp, bootSource);
1818 setBootType(asyncResp, bootType);
1819 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301820}
1821
George Liuc6a620f2020-04-10 17:18:11 +08001822/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001823 * @brief Sets AssetTag
1824 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001825 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001826 * @param[in] assetTag "AssetTag" from request.
1827 *
1828 * @return None.
1829 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001830inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001831 const std::string& assetTag)
1832{
George Liue99073f2022-12-09 11:06:16 +08001833 constexpr std::array<std::string_view, 1> interfaces = {
1834 "xyz.openbmc_project.Inventory.Item.System"};
1835 dbus::utility::getSubTree(
1836 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001837 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001838 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001839 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001840 if (ec)
1841 {
1842 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1843 messages::internalError(asyncResp->res);
1844 return;
1845 }
1846 if (subtree.empty())
1847 {
1848 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1849 messages::internalError(asyncResp->res);
1850 return;
1851 }
1852 // Assume only 1 system D-Bus object
1853 // Throw an error if there is more than 1
1854 if (subtree.size() > 1)
1855 {
1856 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1857 messages::internalError(asyncResp->res);
1858 return;
1859 }
1860 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1861 {
1862 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1863 messages::internalError(asyncResp->res);
1864 return;
1865 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001866
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001867 const std::string& path = subtree[0].first;
1868 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001869
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001870 if (service.empty())
1871 {
1872 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1873 messages::internalError(asyncResp->res);
1874 return;
1875 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001876
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001877 setDbusProperty(asyncResp, "AssetTag", service, path,
1878 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1879 "AssetTag", assetTag);
1880 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001881}
1882
1883/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001884 * @brief Validate the specified stopBootOnFault is valid and return the
1885 * stopBootOnFault name associated with that string
1886 *
1887 * @param[in] stopBootOnFaultString String representing the desired
1888 * stopBootOnFault
1889 *
1890 * @return stopBootOnFault value or empty if incoming value is not valid
1891 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001892inline std::optional<bool> validstopBootOnFault(
1893 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001894{
1895 if (stopBootOnFaultString == "AnyFault")
1896 {
1897 return true;
1898 }
1899
1900 if (stopBootOnFaultString == "Never")
1901 {
1902 return false;
1903 }
1904
1905 return std::nullopt;
1906}
1907
1908/**
1909 * @brief Sets stopBootOnFault
1910 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001911 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001912 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1913 *
1914 * @return None.
1915 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001916inline void setStopBootOnFault(
1917 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1918 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001919{
Ed Tanous62598e32023-07-17 17:06:25 -07001920 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001921
1922 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1923 if (!stopBootEnabled)
1924 {
Ed Tanous62598e32023-07-17 17:06:25 -07001925 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1926 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001927 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001928 "StopBootOnFault");
1929 return;
1930 }
1931
Ginu Georgee93abac2024-06-14 17:35:27 +05301932 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1933 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001934 sdbusplus::message::object_path(
1935 "/xyz/openbmc_project/logging/settings"),
1936 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301937 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001938}
1939
1940/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001941 * @brief Sets automaticRetry (Auto Reboot)
1942 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001943 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001944 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1945 *
1946 * @return None.
1947 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001948inline void setAutomaticRetry(
1949 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1950 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001951{
Ed Tanous62598e32023-07-17 17:06:25 -07001952 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001953
1954 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001955 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001956
1957 if (automaticRetryConfig == "Disabled")
1958 {
1959 autoRebootEnabled = false;
1960 }
1961 else if (automaticRetryConfig == "RetryAttempts")
1962 {
1963 autoRebootEnabled = true;
1964 }
1965 else
1966 {
Ed Tanous62598e32023-07-17 17:06:25 -07001967 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1968 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001969 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001970 "AutomaticRetryConfig");
1971 return;
1972 }
1973
Ginu Georgee93abac2024-06-14 17:35:27 +05301974 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1975 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001976 sdbusplus::message::object_path(
1977 "/xyz/openbmc_project/control/host0/auto_reboot"),
1978 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301979 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001980}
1981
Ed Tanous8d69c662023-06-21 10:29:06 -07001982inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1983{
1984 if (policy == "AlwaysOn")
1985 {
1986 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1987 }
1988 if (policy == "AlwaysOff")
1989 {
1990 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1991 }
1992 if (policy == "LastState")
1993 {
1994 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1995 }
1996 return "";
1997}
1998
Gunnar Mills69f35302020-05-17 16:06:31 -05001999/**
George Liuc6a620f2020-04-10 17:18:11 +08002000 * @brief Sets power restore policy properties.
2001 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002002 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08002003 * @param[in] policy power restore policy properties from request.
2004 *
2005 * @return None.
2006 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002007inline void setPowerRestorePolicy(
2008 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2009 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08002010{
Ed Tanous62598e32023-07-17 17:06:25 -07002011 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08002012
Ed Tanous8d69c662023-06-21 10:29:06 -07002013 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08002014
Ed Tanous8d69c662023-06-21 10:29:06 -07002015 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08002016 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002017 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06002018 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08002019 return;
2020 }
2021
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002022 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05302023 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002024 sdbusplus::message::object_path(
2025 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08002026 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05302027 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08002028}
2029
AppaRao Pulia6349912019-10-18 17:16:08 +05302030/**
2031 * @brief Retrieves provisioning status
2032 *
Ed Tanous25b54db2024-04-17 15:40:31 -07002033 * @param[in] asyncResp Shared pointer for completing asynchronous
2034 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05302035 *
2036 * @return None.
2037 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002038inline void getProvisioningStatus(
2039 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05302040{
Ed Tanous62598e32023-07-17 17:06:25 -07002041 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002042 dbus::utility::getAllProperties(
2043 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2044 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07002045 [asyncResp](const boost::system::error_code& ec,
2046 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002047 nlohmann::json& oemPFR =
2048 asyncResp->res
2049 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
2050 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
2051 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
2052 oemPFR["@odata.type"] =
2053 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07002054
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002055 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05302056 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002057 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2058 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002059 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002060 FirmwareProvisioningStatus::NotProvisioned;
2061 return;
2062 }
2063
2064 const bool* provState = nullptr;
2065 const bool* lockState = nullptr;
2066
2067 const bool success = sdbusplus::unpackPropertiesNoThrow(
2068 dbus_utils::UnpackErrorPrinter(), propertiesList,
2069 "UfmProvisioned", provState, "UfmLocked", lockState);
2070
2071 if (!success)
2072 {
2073 messages::internalError(asyncResp->res);
2074 return;
2075 }
2076
2077 if ((provState == nullptr) || (lockState == nullptr))
2078 {
2079 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2080 messages::internalError(asyncResp->res);
2081 return;
2082 }
2083
2084 if (*provState)
2085 {
2086 if (*lockState)
2087 {
2088 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2089 FirmwareProvisioningStatus::ProvisionedAndLocked;
2090 }
2091 else
2092 {
2093 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2094 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2095 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302096 }
2097 else
2098 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002099 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002100 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302101 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002102 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302103}
AppaRao Pulia6349912019-10-18 17:16:08 +05302104
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302105/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002106 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002107 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002108 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002109 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002110 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002111 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002112inline computer_system::PowerMode translatePowerModeString(
2113 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002114{
Chris Cainb6655102024-02-01 14:35:33 -06002115 using PowerMode = computer_system::PowerMode;
2116
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002117 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002118 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002119 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002120 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002121 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002122 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002123 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002124 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002125 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002126 if (modeString ==
2127 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002128 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002129 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002130 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002131 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002132 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2133 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002134 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002135 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002136 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002137 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2138 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002139 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002140 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002141 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002142 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2143 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002144 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002145 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002146 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002147 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002148 return PowerMode::OEM;
2149 }
2150 // Any other values would be invalid
2151 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2152 return PowerMode::Invalid;
2153}
2154
Patrick Williams504af5a2025-02-03 14:29:03 -05002155inline void afterGetPowerMode(
2156 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2157 const boost::system::error_code& ec,
2158 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002159{
2160 if (ec)
2161 {
2162 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2163 messages::internalError(asyncResp->res);
2164 return;
2165 }
2166
2167 std::string powerMode;
2168 const std::vector<std::string>* allowedModes = nullptr;
2169 const bool success = sdbusplus::unpackPropertiesNoThrow(
2170 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2171 "AllowedPowerModes", allowedModes);
2172
2173 if (!success)
2174 {
2175 messages::internalError(asyncResp->res);
2176 return;
2177 }
2178
2179 nlohmann::json::array_t modeList;
2180 if (allowedModes == nullptr)
2181 {
2182 modeList.emplace_back("Static");
2183 modeList.emplace_back("MaximumPerformance");
2184 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002185 }
2186 else
2187 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002188 for (const auto& aMode : *allowedModes)
2189 {
2190 computer_system::PowerMode modeValue =
2191 translatePowerModeString(aMode);
2192 if (modeValue == computer_system::PowerMode::Invalid)
2193 {
2194 messages::internalError(asyncResp->res);
2195 continue;
2196 }
2197 modeList.emplace_back(modeValue);
2198 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002199 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002200 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002201
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002202 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2203 const computer_system::PowerMode modeValue =
2204 translatePowerModeString(powerMode);
2205 if (modeValue == computer_system::PowerMode::Invalid)
2206 {
2207 messages::internalError(asyncResp->res);
2208 return;
2209 }
2210 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2211}
Chris Cain3a2d04242021-05-28 16:57:10 -05002212/**
2213 * @brief Retrieves system power mode
2214 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002215 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002216 *
2217 * @return None.
2218 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002219inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002220{
Ed Tanous62598e32023-07-17 17:06:25 -07002221 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002222
2223 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002224 constexpr std::array<std::string_view, 1> interfaces = {
2225 "xyz.openbmc_project.Control.Power.Mode"};
2226 dbus::utility::getSubTree(
2227 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002228 [asyncResp](const boost::system::error_code& ec,
2229 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002230 if (ec)
2231 {
2232 BMCWEB_LOG_DEBUG(
2233 "DBUS response error on Power.Mode GetSubTree {}", ec);
2234 // This is an optional D-Bus object so just return if
2235 // error occurs
2236 return;
2237 }
2238 if (subtree.empty())
2239 {
2240 // As noted above, this is an optional interface so just return
2241 // if there is no instance found
2242 return;
2243 }
2244 if (subtree.size() > 1)
2245 {
2246 // More then one PowerMode object is not supported and is an
2247 // error
2248 BMCWEB_LOG_DEBUG(
2249 "Found more than 1 system D-Bus Power.Mode objects: {}",
2250 subtree.size());
2251 messages::internalError(asyncResp->res);
2252 return;
2253 }
2254 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2255 {
2256 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2257 messages::internalError(asyncResp->res);
2258 return;
2259 }
2260 const std::string& path = subtree[0].first;
2261 const std::string& service = subtree[0].second.begin()->first;
2262 if (service.empty())
2263 {
2264 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2265 messages::internalError(asyncResp->res);
2266 return;
2267 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002268
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002269 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002270 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002271 *crow::connections::systemBus, service, path,
2272 "xyz.openbmc_project.Control.Power.Mode",
2273 [asyncResp](
2274 const boost::system::error_code& ec2,
2275 const dbus::utility::DBusPropertiesMap& properties) {
2276 afterGetPowerMode(asyncResp, ec2, properties);
2277 });
George Liue99073f2022-12-09 11:06:16 +08002278 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002279}
2280
2281/**
2282 * @brief Validate the specified mode is valid and return the PowerMode
2283 * name associated with that string
2284 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002285 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002286 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002287 *
2288 * @return PowerMode value or empty string if mode is not valid
2289 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002290inline std::string validatePowerMode(
2291 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2292 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002293{
Chris Cainb6655102024-02-01 14:35:33 -06002294 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002295 std::string mode;
2296
Chris Cainb6655102024-02-01 14:35:33 -06002297 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002298 {
2299 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2300 }
Chris Cainb6655102024-02-01 14:35:33 -06002301 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002302 {
George Liu0fda0f12021-11-16 10:06:17 +08002303 mode =
2304 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002305 }
Chris Cainb6655102024-02-01 14:35:33 -06002306 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002307 {
2308 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2309 }
Chris Cainb6655102024-02-01 14:35:33 -06002310 else if (modeValue == PowerMode::BalancedPerformance)
2311 {
2312 mode =
2313 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2314 }
2315 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2316 {
2317 mode =
2318 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2319 }
2320 else if (modeValue == PowerMode::EfficiencyFavorPower)
2321 {
2322 mode =
2323 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2324 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002325 else
2326 {
Chris Cainb6655102024-02-01 14:35:33 -06002327 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002328 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002329 }
2330 return mode;
2331}
2332
2333/**
2334 * @brief Sets system power mode.
2335 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002336 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002337 * @param[in] pmode System power mode from request.
2338 *
2339 * @return None.
2340 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002341inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002342 const std::string& pmode)
2343{
Ed Tanous62598e32023-07-17 17:06:25 -07002344 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002345
Ed Tanousac106bf2023-06-07 09:24:59 -07002346 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002347 if (powerMode.empty())
2348 {
2349 return;
2350 }
2351
2352 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002353 constexpr std::array<std::string_view, 1> interfaces = {
2354 "xyz.openbmc_project.Control.Power.Mode"};
2355 dbus::utility::getSubTree(
2356 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002357 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002358 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002359 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002360 if (ec)
2361 {
2362 BMCWEB_LOG_ERROR(
2363 "DBUS response error on Power.Mode GetSubTree {}", ec);
2364 // This is an optional D-Bus object, but user attempted to patch
2365 messages::internalError(asyncResp->res);
2366 return;
2367 }
2368 if (subtree.empty())
2369 {
2370 // This is an optional D-Bus object, but user attempted to patch
2371 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2372 "PowerMode");
2373 return;
2374 }
2375 if (subtree.size() > 1)
2376 {
2377 // More then one PowerMode object is not supported and is an
2378 // error
2379 BMCWEB_LOG_DEBUG(
2380 "Found more than 1 system D-Bus Power.Mode objects: {}",
2381 subtree.size());
2382 messages::internalError(asyncResp->res);
2383 return;
2384 }
2385 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2386 {
2387 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2388 messages::internalError(asyncResp->res);
2389 return;
2390 }
2391 const std::string& path = subtree[0].first;
2392 const std::string& service = subtree[0].second.begin()->first;
2393 if (service.empty())
2394 {
2395 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2396 messages::internalError(asyncResp->res);
2397 return;
2398 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002399
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002400 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002401
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002402 // Set the Power Mode property
2403 setDbusProperty(asyncResp, "PowerMode", service, path,
2404 "xyz.openbmc_project.Control.Power.Mode",
2405 "PowerMode", powerMode);
2406 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002407}
2408
2409/**
Yong Li51709ff2019-09-30 14:13:04 +08002410 * @brief Translates watchdog timeout action DBUS property value to redfish.
2411 *
2412 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2413 *
2414 * @return Returns as a string, the timeout action in Redfish terms. If
2415 * translation cannot be done, returns an empty string.
2416 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002417inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002418{
2419 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2420 {
2421 return "None";
2422 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002423 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002424 {
2425 return "ResetSystem";
2426 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002427 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002428 {
2429 return "PowerDown";
2430 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002431 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002432 {
2433 return "PowerCycle";
2434 }
2435
2436 return "";
2437}
2438
2439/**
Yong Lic45f0082019-10-10 14:19:01 +08002440 *@brief Translates timeout action from Redfish to DBUS property value.
2441 *
2442 *@param[in] rfAction The timeout action in Redfish.
2443 *
2444 *@return Returns as a string, the time_out action as expected by DBUS.
2445 *If translation cannot be done, returns an empty string.
2446 */
2447
Ed Tanous23a21a12020-07-25 04:45:05 +00002448inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002449{
2450 if (rfAction == "None")
2451 {
2452 return "xyz.openbmc_project.State.Watchdog.Action.None";
2453 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002454 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002455 {
2456 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2457 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002458 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002459 {
2460 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2461 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002462 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002463 {
2464 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2465 }
2466
2467 return "";
2468}
2469
2470/**
Yong Li51709ff2019-09-30 14:13:04 +08002471 * @brief Retrieves host watchdog timer properties over DBUS
2472 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002473 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002474 *
2475 * @return None.
2476 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002477inline void getHostWatchdogTimer(
2478 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002479{
Ed Tanous62598e32023-07-17 17:06:25 -07002480 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002481 dbus::utility::getAllProperties(
2482 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002483 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002484 [asyncResp](const boost::system::error_code& ec,
2485 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002486 if (ec)
2487 {
2488 // watchdog service is stopped
2489 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2490 return;
2491 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002492
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002493 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002494
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002495 nlohmann::json& hostWatchdogTimer =
2496 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002497
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002498 // watchdog service is running/enabled
2499 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002500
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002501 const bool* enabled = nullptr;
2502 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002503
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002504 const bool success = sdbusplus::unpackPropertiesNoThrow(
2505 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2506 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002507
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002508 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002509 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002510 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002511 return;
2512 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002513
2514 if (enabled != nullptr)
2515 {
2516 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2517 }
2518
2519 if (expireAction != nullptr)
2520 {
2521 std::string action = dbusToRfWatchdogAction(*expireAction);
2522 if (action.empty())
2523 {
2524 messages::internalError(asyncResp->res);
2525 return;
2526 }
2527 hostWatchdogTimer["TimeoutAction"] = action;
2528 }
2529 });
Yong Li51709ff2019-09-30 14:13:04 +08002530}
2531
2532/**
Yong Lic45f0082019-10-10 14:19:01 +08002533 * @brief Sets Host WatchDog Timer properties.
2534 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002535 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002536 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2537 * RF request.
2538 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2539 *
2540 * @return None.
2541 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002542inline void setWDTProperties(
2543 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2544 const std::optional<bool> wdtEnable,
2545 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002546{
Ed Tanous62598e32023-07-17 17:06:25 -07002547 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002548
2549 if (wdtTimeOutAction)
2550 {
2551 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2552 // check if TimeOut Action is Valid
2553 if (wdtTimeOutActStr.empty())
2554 {
Ed Tanous62598e32023-07-17 17:06:25 -07002555 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2556 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002557 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002558 "TimeoutAction");
2559 return;
2560 }
2561
Ginu Georgee93abac2024-06-14 17:35:27 +05302562 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2563 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002564 sdbusplus::message::object_path(
2565 "/xyz/openbmc_project/watchdog/host0"),
2566 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302567 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002568 }
2569
2570 if (wdtEnable)
2571 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302572 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2573 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002574 sdbusplus::message::object_path(
2575 "/xyz/openbmc_project/watchdog/host0"),
2576 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302577 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002578 }
2579}
2580
Chris Cain37bbf982021-09-20 10:53:09 -05002581/**
2582 * @brief Parse the Idle Power Saver properties into json
2583 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002584 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002585 * @param[in] properties IPS property data from DBus.
2586 *
2587 * @return true if successful
2588 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002589inline bool parseIpsProperties(
2590 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2591 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002592{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002593 const bool* enabled = nullptr;
2594 const uint8_t* enterUtilizationPercent = nullptr;
2595 const uint64_t* enterDwellTime = nullptr;
2596 const uint8_t* exitUtilizationPercent = nullptr;
2597 const uint64_t* exitDwellTime = nullptr;
2598
2599 const bool success = sdbusplus::unpackPropertiesNoThrow(
2600 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002601 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2602 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2603 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002604
2605 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002606 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002607 return false;
2608 }
2609
2610 if (enabled != nullptr)
2611 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002612 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002613 }
2614
2615 if (enterUtilizationPercent != nullptr)
2616 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002617 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002618 *enterUtilizationPercent;
2619 }
2620
2621 if (enterDwellTime != nullptr)
2622 {
2623 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002624 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002625 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2626 .count();
2627 }
2628
2629 if (exitUtilizationPercent != nullptr)
2630 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002631 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002632 *exitUtilizationPercent;
2633 }
2634
2635 if (exitDwellTime != nullptr)
2636 {
2637 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002638 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002639 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2640 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002641 }
2642
2643 return true;
2644}
2645
2646/**
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002647 * @brief Retrieves idle power saver properties over DBUS
Chris Cain37bbf982021-09-20 10:53:09 -05002648 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002649 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002650 *
2651 * @return None.
2652 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002653inline void getIdlePowerSaver(
2654 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002655{
Ed Tanous62598e32023-07-17 17:06:25 -07002656 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002657
2658 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002659 constexpr std::array<std::string_view, 1> interfaces = {
2660 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2661 dbus::utility::getSubTree(
2662 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002663 [asyncResp](const boost::system::error_code& ec,
2664 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002665 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002666 {
Ed Tanous62598e32023-07-17 17:06:25 -07002667 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002668 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2669 ec);
2670 messages::internalError(asyncResp->res);
2671 return;
2672 }
2673 if (subtree.empty())
2674 {
2675 // This is an optional interface so just return
2676 // if there is no instance found
2677 BMCWEB_LOG_DEBUG("No instances found");
2678 return;
2679 }
2680 if (subtree.size() > 1)
2681 {
2682 // More then one PowerIdlePowerSaver object is not supported and
2683 // is an error
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002684 BMCWEB_LOG_DEBUG(
2685 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2686 subtree.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002687 messages::internalError(asyncResp->res);
2688 return;
2689 }
2690 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2691 {
2692 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2693 messages::internalError(asyncResp->res);
2694 return;
2695 }
2696 const std::string& path = subtree[0].first;
2697 const std::string& service = subtree[0].second.begin()->first;
2698 if (service.empty())
2699 {
2700 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002701 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002702 return;
2703 }
2704
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002705 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002706 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002707 *crow::connections::systemBus, service, path,
2708 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2709 [asyncResp](
2710 const boost::system::error_code& ec2,
2711 const dbus::utility::DBusPropertiesMap& properties) {
2712 if (ec2)
2713 {
2714 BMCWEB_LOG_ERROR(
2715 "DBUS response error on IdlePowerSaver GetAll: {}",
2716 ec2);
2717 messages::internalError(asyncResp->res);
2718 return;
2719 }
2720
2721 if (!parseIpsProperties(asyncResp, properties))
2722 {
2723 messages::internalError(asyncResp->res);
2724 return;
2725 }
2726 });
George Liue99073f2022-12-09 11:06:16 +08002727 });
Chris Cain37bbf982021-09-20 10:53:09 -05002728
Ed Tanous62598e32023-07-17 17:06:25 -07002729 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002730}
2731
2732/**
2733 * @brief Sets Idle Power Saver properties.
2734 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002735 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002736 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2737 * RF request.
2738 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2739 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2740 * before entering idle state.
2741 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2742 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2743 * before exiting idle state
2744 *
2745 * @return None.
2746 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002747inline void setIdlePowerSaver(
2748 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2749 const std::optional<bool> ipsEnable,
2750 const std::optional<uint8_t> ipsEnterUtil,
2751 const std::optional<uint64_t> ipsEnterTime,
2752 const std::optional<uint8_t> ipsExitUtil,
2753 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002754{
Ed Tanous62598e32023-07-17 17:06:25 -07002755 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002756
2757 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002758 constexpr std::array<std::string_view, 1> interfaces = {
2759 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2760 dbus::utility::getSubTree(
2761 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002762 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002763 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002764 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002765 if (ec)
2766 {
2767 BMCWEB_LOG_ERROR(
2768 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2769 ec);
2770 messages::internalError(asyncResp->res);
2771 return;
2772 }
2773 if (subtree.empty())
2774 {
2775 // This is an optional D-Bus object, but user attempted to patch
2776 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2777 "IdlePowerSaver");
2778 return;
2779 }
2780 if (subtree.size() > 1)
2781 {
2782 // More then one PowerIdlePowerSaver object is not supported and
2783 // is an error
2784 BMCWEB_LOG_DEBUG(
2785 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2786 subtree.size());
2787 messages::internalError(asyncResp->res);
2788 return;
2789 }
2790 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2791 {
2792 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2793 messages::internalError(asyncResp->res);
2794 return;
2795 }
2796 const std::string& path = subtree[0].first;
2797 const std::string& service = subtree[0].second.begin()->first;
2798 if (service.empty())
2799 {
2800 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2801 messages::internalError(asyncResp->res);
2802 return;
2803 }
Chris Cain37bbf982021-09-20 10:53:09 -05002804
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002805 // Valid Power IdlePowerSaver object found, now set any values that
2806 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002807
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002808 if (ipsEnable)
2809 {
2810 setDbusProperty(
2811 asyncResp, "IdlePowerSaver/Enabled", service, path,
2812 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2813 "Enabled", *ipsEnable);
2814 }
2815 if (ipsEnterUtil)
2816 {
2817 setDbusProperty(
2818 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2819 service, path,
2820 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2821 "EnterUtilizationPercent", *ipsEnterUtil);
2822 }
2823 if (ipsEnterTime)
2824 {
2825 // Convert from seconds into milliseconds for DBus
2826 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2827 setDbusProperty(
2828 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2829 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2830 "EnterDwellTime", timeMilliseconds);
2831 }
2832 if (ipsExitUtil)
2833 {
2834 setDbusProperty(
2835 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2836 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2837 "ExitUtilizationPercent", *ipsExitUtil);
2838 }
2839 if (ipsExitTime)
2840 {
2841 // Convert from seconds into milliseconds for DBus
2842 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2843 setDbusProperty(
2844 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2845 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2846 "ExitDwellTime", timeMilliseconds);
2847 }
2848 });
Chris Cain37bbf982021-09-20 10:53:09 -05002849
Ed Tanous62598e32023-07-17 17:06:25 -07002850 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002851}
2852
Ed Tanousc1e219d2023-06-07 10:34:33 -07002853inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002854 crow::App& app, const crow::Request& req,
2855 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2856{
2857 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2858 {
2859 return;
2860 }
2861 asyncResp->res.addHeader(
2862 boost::beast::http::field::link,
2863 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2864}
2865
Ed Tanousc1e219d2023-06-07 10:34:33 -07002866inline void handleComputerSystemCollectionGet(
2867 crow::App& app, const crow::Request& req,
2868 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2869{
2870 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2871 {
2872 return;
2873 }
2874
2875 asyncResp->res.addHeader(
2876 boost::beast::http::field::link,
2877 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2878 asyncResp->res.jsonValue["@odata.type"] =
2879 "#ComputerSystemCollection.ComputerSystemCollection";
2880 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2881 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2882
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002883 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002884}
2885
Yong Lic45f0082019-10-10 14:19:01 +08002886/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002887 * Function transceives data with dbus directly.
2888 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002889inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002890{
Patrick Williams89492a12023-05-10 07:51:34 -05002891 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2892 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2893 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002894 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002895 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002896
Ed Tanous177612a2025-02-14 15:16:09 -08002897 dbus::utility::async_method_call(
2898 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002899 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002900 if (ec)
2901 {
2902 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2903 messages::internalError(asyncResp->res);
2904 return;
2905 }
2906 messages::success(asyncResp->res);
2907 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002908 serviceName, objectPath, interfaceName, method);
2909}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002910
Ed Tanousc1e219d2023-06-07 10:34:33 -07002911inline void handleComputerSystemResetActionPost(
2912 crow::App& app, const crow::Request& req,
2913 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2914 const std::string& systemName)
2915{
2916 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2917 {
2918 return;
2919 }
Gunnar Millsdd7090e2024-07-30 15:23:05 -05002920
2921 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2922 {
2923 if (systemName == "hypervisor")
2924 {
2925 handleHypervisorSystemResetPost(req, asyncResp);
2926 return;
2927 }
2928 }
2929
Ed Tanous253f11b2024-05-16 09:38:31 -07002930 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002931 {
2932 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2933 systemName);
2934 return;
2935 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002936 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002937 {
2938 // Option currently returns no systems. TBD
2939 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2940 systemName);
2941 return;
2942 }
2943 std::string resetType;
2944 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2945 {
2946 return;
2947 }
2948
2949 // Get the command and host vs. chassis
2950 std::string command;
2951 bool hostCommand = true;
2952 if ((resetType == "On") || (resetType == "ForceOn"))
2953 {
2954 command = "xyz.openbmc_project.State.Host.Transition.On";
2955 hostCommand = true;
2956 }
2957 else if (resetType == "ForceOff")
2958 {
2959 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2960 hostCommand = false;
2961 }
2962 else if (resetType == "ForceRestart")
2963 {
2964 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2965 hostCommand = true;
2966 }
2967 else if (resetType == "GracefulShutdown")
2968 {
2969 command = "xyz.openbmc_project.State.Host.Transition.Off";
2970 hostCommand = true;
2971 }
2972 else if (resetType == "GracefulRestart")
2973 {
2974 command =
2975 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2976 hostCommand = true;
2977 }
2978 else if (resetType == "PowerCycle")
2979 {
2980 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2981 hostCommand = true;
2982 }
2983 else if (resetType == "Nmi")
2984 {
2985 doNMI(asyncResp);
2986 return;
2987 }
2988 else
2989 {
2990 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2991 return;
2992 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002993 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002994
2995 if (hostCommand)
2996 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302997 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002998 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302999 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003000 }
3001 else
3002 {
Ginu Georgee93abac2024-06-14 17:35:27 +05303003 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08003004 statePath / "chassis0",
3005 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05303006 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003007 }
3008}
3009
Ed Tanousc1e219d2023-06-07 10:34:33 -07003010inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003011 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003012 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3013 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003014{
3015 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3016 {
3017 return;
3018 }
3019
3020 asyncResp->res.addHeader(
3021 boost::beast::http::field::link,
3022 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3023}
3024
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003025inline void afterPortRequest(
3026 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3027 const boost::system::error_code& ec,
3028 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3029{
3030 if (ec)
3031 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003032 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003033 messages::internalError(asyncResp->res);
3034 return;
3035 }
3036 for (const auto& data : socketData)
3037 {
3038 const std::string& socketPath = get<0>(data);
3039 const std::string& protocolName = get<1>(data);
3040 bool isProtocolEnabled = get<2>(data);
3041 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3042 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3043 // need to retrieve port number for
3044 // obmc-console-ssh service
3045 if (protocolName == "SSH")
3046 {
3047 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003048 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003049 int portNumber) {
3050 if (ec1)
3051 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003052 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003053 messages::internalError(asyncResp->res);
3054 return;
3055 }
3056 nlohmann::json& dataJson1 =
3057 asyncResp->res.jsonValue["SerialConsole"];
3058 dataJson1[protocolName]["Port"] = portNumber;
3059 });
3060 }
3061 }
3062}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003063
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003064/**
3065 * @brief process the GET request after getting the computerSystemIndex
3066 *
3067 * @param[in] asyncResp Shared pointer for completing asynchronous
3068 * calls
3069 * @param[in] systemName Name of the requested system
3070 * @param[in] computerSystemIndex Index associated with the requested system
3071 *
3072 * @return None
3073 */
3074inline void processComputerSystemGet(
Patrick Williams504af5a2025-02-03 14:29:03 -05003075 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003076 const std::string& systemName, const uint64_t computerSystemIndex)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003077{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003078 asyncResp->res.addHeader(
3079 boost::beast::http::field::link,
3080 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3081 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003082 "#ComputerSystem.v1_22_0.ComputerSystem";
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003083 asyncResp->res.jsonValue["Name"] = systemName;
3084 asyncResp->res.jsonValue["Id"] = systemName;
Ed Tanous539d8c62024-06-19 14:38:27 -07003085 asyncResp->res.jsonValue["SystemType"] =
3086 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003087 asyncResp->res.jsonValue["Description"] = "Computer System";
3088 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003089 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003090 double(0);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003091 asyncResp->res.jsonValue["@odata.id"] =
3092 boost::urls::format("/redfish/v1/Systems/{}", systemName);
Ed Tanous04a258f2018-10-15 08:00:41 -07003093
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003094 // Currently not supported on multi-host. TBD
3095 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3096 {
3097 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3098 boost::urls::format("/redfish/v1/Systems/{}/Bios", systemName);
3099 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3100 boost::urls::format("/redfish/v1/Systems/{}/Processors",
3101 systemName);
3102 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3103 boost::urls::format("/redfish/v1/Systems/{}/Memory", systemName);
3104 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3105 boost::urls::format("/redfish/v1/Systems/{}/Storage", systemName);
3106 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3107 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3108 systemName);
3109 }
Ed Tanous029573d2019-02-01 10:57:49 -08003110
Ed Tanousc1e219d2023-06-07 10:34:33 -07003111 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003112 boost::urls::format(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003113 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003114 asyncResp->res
3115 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003116 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003117 systemName);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003118
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003119 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3120 boost::urls::format("/redfish/v1/Systems/{}/LogServices", systemName);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003121
Ed Tanousc1e219d2023-06-07 10:34:33 -07003122 nlohmann::json::array_t managedBy;
3123 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003124 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3125 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003126 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003127 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3128 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003129
Ed Tanousc1e219d2023-06-07 10:34:33 -07003130 // Fill in SerialConsole info
3131 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3132 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003133
Ed Tanousc1e219d2023-06-07 10:34:33 -07003134 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3135 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3136 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3137 "Press ~. to exit console";
3138 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3139 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003140
Ed Tanous25b54db2024-04-17 15:40:31 -07003141 if constexpr (BMCWEB_KVM)
3142 {
3143 // Fill in GraphicalConsole info
3144 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3145 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3146 4;
3147 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3148 nlohmann::json::array_t({"KVMIP"});
3149 }
James Feistb49ac872019-05-21 15:12:01 -07003150
Janet Adkins2eaa9272025-04-17 10:30:43 -05003151 systems_utils::getValidSystemsPath(
3152 asyncResp, systemName,
3153 [asyncResp,
3154 systemName](const std::optional<std::string>& validSystemsPath) {
3155 if (validSystemsPath)
3156 {
3157 getLocationIndicatorActive(asyncResp, *validSystemsPath);
3158 }
3159 });
3160
Janet Adkinsf664fd82025-07-23 14:01:43 -05003161 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3162 {
3163 getIndicatorLedState(asyncResp);
3164 }
3165
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003166 // Currently not supported on multi-host.
3167 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3168 {
3169 getComputerSystem(asyncResp);
3170 // Todo: chassis matching could be handled by patch
3171 // https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60793
3172 getMainChassisId(
3173 asyncResp, [](const std::string& chassisId,
3174 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3175 nlohmann::json::array_t chassisArray;
3176 nlohmann::json& chassis = chassisArray.emplace_back();
3177 chassis["@odata.id"] =
3178 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3179 aRsp->res.jsonValue["Links"]["Chassis"] =
3180 std::move(chassisArray);
3181 });
3182
3183 pcie_util::getPCIeDeviceList(
3184 asyncResp, nlohmann::json::json_pointer("/PCIeDevices"));
3185 }
3186 getHostState(asyncResp, computerSystemIndex);
3187 getBootProperties(asyncResp, computerSystemIndex);
3188 getBootProgress(asyncResp, computerSystemIndex);
3189 getBootProgressLastStateTime(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003190 getHostWatchdogTimer(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003191 getPowerRestorePolicy(asyncResp, computerSystemIndex);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003192 getStopBootOnFault(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003193 getAutomaticRetryPolicy(asyncResp, computerSystemIndex);
3194 getLastResetTime(asyncResp, computerSystemIndex);
Ed Tanous25b54db2024-04-17 15:40:31 -07003195 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3196 {
3197 getProvisioningStatus(asyncResp);
3198 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003199 getTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003200 getPowerMode(asyncResp);
3201 getIdlePowerSaver(asyncResp);
3202}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003203
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003204inline void handleComputerSystemGet(
3205 crow::App& app, const crow::Request& req,
3206 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3207 const std::string& systemName)
3208{
3209 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3210 {
3211 return;
3212 }
3213
3214 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
3215 {
3216 if (systemName == "hypervisor")
3217 {
3218 handleHypervisorSystemGet(asyncResp);
3219 return;
3220 }
3221 }
3222
3223 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3224 {
3225 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3226 {
3227 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3228 systemName);
3229 return;
3230 }
3231 }
3232
3233 BMCWEB_LOG_DEBUG("requested system = {}", systemName);
3234 getComputerSystemIndex(
3235 asyncResp, systemName,
3236 std::bind_front(processComputerSystemGet, asyncResp, systemName));
3237}
3238
Ed Tanousc1e219d2023-06-07 10:34:33 -07003239inline void handleComputerSystemPatch(
3240 crow::App& app, const crow::Request& req,
3241 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3242 const std::string& systemName)
3243{
3244 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3245 {
3246 return;
3247 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003248 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003249 {
3250 // Option currently returns no systems. TBD
3251 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3252 systemName);
3253 return;
3254 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003255 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003256 {
3257 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3258 systemName);
3259 return;
3260 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003261
Ed Tanousc1e219d2023-06-07 10:34:33 -07003262 asyncResp->res.addHeader(
3263 boost::beast::http::field::link,
3264 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003265
Ed Tanousc1e219d2023-06-07 10:34:33 -07003266 std::optional<bool> locationIndicatorActive;
3267 std::optional<std::string> indicatorLed;
3268 std::optional<std::string> assetTag;
3269 std::optional<std::string> powerRestorePolicy;
3270 std::optional<std::string> powerMode;
3271 std::optional<bool> wdtEnable;
3272 std::optional<std::string> wdtTimeOutAction;
3273 std::optional<std::string> bootSource;
3274 std::optional<std::string> bootType;
3275 std::optional<std::string> bootEnable;
3276 std::optional<std::string> bootAutomaticRetry;
3277 std::optional<uint32_t> bootAutomaticRetryAttempts;
3278 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003279 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003280 std::optional<bool> ipsEnable;
3281 std::optional<uint8_t> ipsEnterUtil;
3282 std::optional<uint64_t> ipsEnterTime;
3283 std::optional<uint8_t> ipsExitUtil;
3284 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003285
Patrick Williams504af5a2025-02-03 14:29:03 -05003286 if (!json_util::readJsonPatch( //
3287 req, asyncResp->res, //
3288 "AssetTag", assetTag, //
3289 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts, //
3290 "Boot/AutomaticRetryConfig", bootAutomaticRetry, //
3291 "Boot/BootSourceOverrideEnabled", bootEnable, //
3292 "Boot/BootSourceOverrideMode", bootType, //
3293 "Boot/BootSourceOverrideTarget", bootSource, //
3294 "Boot/StopBootOnFault", stopBootOnFault, //
Myung Baeafc474a2024-10-09 00:53:29 -07003295 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired, //
Patrick Williams504af5a2025-02-03 14:29:03 -05003296 "HostWatchdogTimer/FunctionEnabled", wdtEnable, //
3297 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction, //
3298 "IdlePowerSaver/Enabled", ipsEnable, //
3299 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime, //
3300 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil, //
3301 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime, //
3302 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil, //
3303 "IndicatorLED", indicatorLed, //
3304 "LocationIndicatorActive", locationIndicatorActive, //
3305 "PowerMode", powerMode, //
3306 "PowerRestorePolicy", powerRestorePolicy //
Myung Baeafc474a2024-10-09 00:53:29 -07003307 ))
Ed Tanousab344222024-08-07 18:01:23 -07003308 {
3309 return;
3310 }
James Feistb49ac872019-05-21 15:12:01 -07003311
Janet Adkinsf664fd82025-07-23 14:01:43 -05003312 if constexpr (!BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3313 {
3314 if (indicatorLed)
3315 {
3316 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
3317 return;
3318 }
3319 }
3320
Ed Tanousc1e219d2023-06-07 10:34:33 -07003321 if (assetTag)
3322 {
3323 setAssetTag(asyncResp, *assetTag);
3324 }
James Feistb49ac872019-05-21 15:12:01 -07003325
Ed Tanousc1e219d2023-06-07 10:34:33 -07003326 if (wdtEnable || wdtTimeOutAction)
3327 {
3328 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3329 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003330
Ed Tanousc1e219d2023-06-07 10:34:33 -07003331 if (bootSource || bootType || bootEnable)
3332 {
3333 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3334 }
3335 if (bootAutomaticRetry)
3336 {
3337 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3338 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003339
Ed Tanousc1e219d2023-06-07 10:34:33 -07003340 if (bootAutomaticRetryAttempts)
3341 {
3342 setAutomaticRetryAttempts(asyncResp,
3343 bootAutomaticRetryAttempts.value());
3344 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003345
Ed Tanousc1e219d2023-06-07 10:34:33 -07003346 if (bootTrustedModuleRequired)
3347 {
3348 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3349 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003350
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003351 if (stopBootOnFault)
3352 {
3353 setStopBootOnFault(asyncResp, *stopBootOnFault);
3354 }
3355
Ed Tanousc1e219d2023-06-07 10:34:33 -07003356 if (locationIndicatorActive)
3357 {
Janet Adkins2eaa9272025-04-17 10:30:43 -05003358 systems_utils::getValidSystemsPath(
3359 asyncResp, systemName,
3360 [asyncResp, systemName,
3361 locationIndicatorActive{*locationIndicatorActive}](
3362 const std::optional<std::string>& validSystemsPath) {
3363 if (!validSystemsPath)
3364 {
3365 messages::resourceNotFound(asyncResp->res, "Systems",
3366 systemName);
3367 return;
3368 }
3369 setLocationIndicatorActive(asyncResp, *validSystemsPath,
3370 locationIndicatorActive);
3371 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003372 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003373
Janet Adkinsf664fd82025-07-23 14:01:43 -05003374 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003375 {
Janet Adkinsf664fd82025-07-23 14:01:43 -05003376 if (indicatorLed)
3377 {
3378 setIndicatorLedState(asyncResp, *indicatorLed);
3379 asyncResp->res.addHeader(boost::beast::http::field::warning,
3380 "299 - \"IndicatorLED is deprecated. Use "
3381 "LocationIndicatorActive instead.\"");
3382 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003383 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003384
Ed Tanousc1e219d2023-06-07 10:34:33 -07003385 if (powerRestorePolicy)
3386 {
3387 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3388 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003389
Ed Tanousc1e219d2023-06-07 10:34:33 -07003390 if (powerMode)
3391 {
3392 setPowerMode(asyncResp, *powerMode);
3393 }
Chris Cain37bbf982021-09-20 10:53:09 -05003394
Ed Tanousc1e219d2023-06-07 10:34:33 -07003395 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3396 {
3397 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3398 ipsExitUtil, ipsExitTime);
3399 }
3400}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303401
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003402inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003403 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003404 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003405 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003406{
3407 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3408 {
3409 return;
3410 }
3411 asyncResp->res.addHeader(
3412 boost::beast::http::field::link,
3413 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3414}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003415
3416/**
3417 * @brief Translates allowed host transitions to redfish string
3418 *
3419 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3420 * @param[out] allowableValues The translated host transition(s)
3421 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303422 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003423 * allowableValues. If translation not possible, does nothing to
3424 * allowableValues.
3425 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003426inline void dbusToRfAllowedHostTransitions(
3427 const std::string& dbusAllowedHostTran,
3428 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003429{
3430 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3431 {
3432 allowableValues.emplace_back(resource::ResetType::On);
3433 allowableValues.emplace_back(resource::ResetType::ForceOn);
3434 }
3435 else if (dbusAllowedHostTran ==
3436 "xyz.openbmc_project.State.Host.Transition.Off")
3437 {
3438 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3439 }
3440 else if (dbusAllowedHostTran ==
3441 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3442 {
3443 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3444 }
3445 else if (dbusAllowedHostTran ==
3446 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3447 {
3448 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3449 }
3450 else
3451 {
3452 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3453 }
3454}
3455
3456inline void afterGetAllowedHostTransitions(
3457 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3458 const boost::system::error_code& ec,
3459 const std::vector<std::string>& allowedHostTransitions)
3460{
3461 nlohmann::json::array_t allowableValues;
3462
3463 // Supported on all systems currently
3464 allowableValues.emplace_back(resource::ResetType::ForceOff);
3465 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3466 allowableValues.emplace_back(resource::ResetType::Nmi);
3467
3468 if (ec)
3469 {
Ed Tanouse715d142024-03-07 15:47:37 -08003470 if ((ec.value() ==
3471 boost::system::linux_error::bad_request_descriptor) ||
3472 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003473 {
3474 // Property not implemented so just return defaults
3475 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3476 allowableValues.emplace_back(resource::ResetType::On);
3477 allowableValues.emplace_back(resource::ResetType::ForceOn);
3478 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3479 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3480 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3481 }
3482 else
3483 {
3484 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3485 messages::internalError(asyncResp->res);
3486 return;
3487 }
3488 }
3489 else
3490 {
3491 for (const std::string& transition : allowedHostTransitions)
3492 {
3493 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3494 dbusToRfAllowedHostTransitions(transition, allowableValues);
3495 }
3496 }
3497
3498 nlohmann::json::object_t parameter;
3499 parameter["Name"] = "ResetType";
3500 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003501 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003502 parameter["AllowableValues"] = std::move(allowableValues);
3503 nlohmann::json::array_t parameters;
3504 parameters.emplace_back(std::move(parameter));
3505 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3506}
3507
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003508inline void getAllowedHostTransitions(
3509 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3510 const uint64_t computerSystemIndex)
3511{
3512 dbus::utility::getProperty<std::vector<std::string>>(
3513 getHostStateServiceName(computerSystemIndex),
3514 getHostStateObjectPath(computerSystemIndex),
3515 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
3516 std::bind_front(afterGetAllowedHostTransitions, asyncResp));
3517}
3518
Ed Tanousc1e219d2023-06-07 10:34:33 -07003519inline void handleSystemCollectionResetActionGet(
3520 crow::App& app, const crow::Request& req,
3521 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3522 const std::string& systemName)
3523{
3524 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3525 {
3526 return;
3527 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003528
Gunnar Mills68896202024-08-21 11:34:20 -05003529 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003530 {
Gunnar Mills68896202024-08-21 11:34:20 -05003531 if (systemName == "hypervisor")
3532 {
3533 handleHypervisorResetActionGet(asyncResp);
3534 return;
3535 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003536 }
3537
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003538 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003539 {
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003540 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3541 {
3542 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3543 systemName);
3544 return;
3545 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003546 }
3547
3548 asyncResp->res.addHeader(
3549 boost::beast::http::field::link,
3550 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3551
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003552 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3553 "/redfish/v1/Systems/{}/ResetActionInfo", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003554 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3555 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3556 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3557
Andrew Geissler33e1f122024-02-26 21:10:16 -06003558 // Look to see if system defines AllowedHostTransitions
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003559 getComputerSystemIndex(
3560 asyncResp, systemName,
3561 std::bind_front(getAllowedHostTransitions, asyncResp));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003562}
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003563
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303564/**
3565 * SystemResetActionInfo derived class for delivering Computer Systems
3566 * ResetType AllowableValues using ResetInfo schema.
3567 */
Ed Tanous100afe52023-06-07 13:30:46 -07003568inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303569{
Ed Tanous100afe52023-06-07 13:30:46 -07003570 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3571 .privileges(redfish::privileges::headComputerSystemCollection)
3572 .methods(boost::beast::http::verb::head)(
3573 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3574
3575 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3576 .privileges(redfish::privileges::getComputerSystemCollection)
3577 .methods(boost::beast::http::verb::get)(
3578 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3579
3580 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3581 .privileges(redfish::privileges::headComputerSystem)
3582 .methods(boost::beast::http::verb::head)(
3583 std::bind_front(handleComputerSystemHead, std::ref(app)));
3584
3585 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3586 .privileges(redfish::privileges::getComputerSystem)
3587 .methods(boost::beast::http::verb::get)(
3588 std::bind_front(handleComputerSystemGet, std::ref(app)));
3589
3590 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3591 .privileges(redfish::privileges::patchComputerSystem)
3592 .methods(boost::beast::http::verb::patch)(
3593 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3594
3595 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3596 .privileges(redfish::privileges::postComputerSystem)
3597 .methods(boost::beast::http::verb::post)(std::bind_front(
3598 handleComputerSystemResetActionPost, std::ref(app)));
3599
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003600 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003601 .privileges(redfish::privileges::headActionInfo)
3602 .methods(boost::beast::http::verb::head)(std::bind_front(
3603 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003604 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003605 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003606 .methods(boost::beast::http::verb::get)(std::bind_front(
3607 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003608}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003609} // namespace redfish