blob: 129c59a16e453bdfe4594ac930169eb68e4bbc0a [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"
Ed Tanous2b829372022-08-03 14:22:34 -070028#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080029
Ed Tanousd7857202025-01-28 15:32:26 -080030#include <asm-generic/errno.h>
31
Andrew Geisslerfc903b32023-05-31 14:15:42 -040032#include <boost/asio/error.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <boost/beast/http/field.hpp>
34#include <boost/beast/http/status.hpp>
35#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080036#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060037#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070038#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080039#include <nlohmann/json.hpp>
40#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020041#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042
George Liu7a1dbc42022-12-07 16:03:22 +080043#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080044#include <chrono>
45#include <cstddef>
46#include <cstdint>
47#include <functional>
Andrew Geissler33e1f122024-02-26 21:10:16 -060048#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080049#include <optional>
50#include <ratio>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060051#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080052#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080053#include <tuple>
Ed Tanous20fa6a22024-05-20 18:02:58 -070054#include <utility>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060055#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020056
Ed Tanous1abe55e2018-09-05 08:30:59 -070057namespace redfish
58{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020059
Abhishek Patel5c3e9272021-06-24 10:11:33 -050060const static std::array<std::pair<std::string_view, std::string_view>, 2>
61 protocolToDBusForSystems{
62 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
63
Alpana Kumari9d3ae102019-04-12 06:49:32 -050064/**
65 * @brief Updates the Functional State of DIMMs
66 *
Ed Tanousac106bf2023-06-07 09:24:59 -070067 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050068 * @param[in] dimmState Dimm's Functional state, true/false
69 *
70 * @return None.
71 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040072inline void updateDimmProperties(
73 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050074{
Ed Tanous62598e32023-07-17 17:06:25 -070075 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050076
Gunnar Mills4e0453b2020-07-08 14:00:30 -050077 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050078 // Update STATE only if previous State was DISABLED and current Dimm is
79 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070080 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070081 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050082 if (prevMemSummary == "Disabled")
83 {
Ed Tanouse05aec52022-01-25 10:28:56 -080084 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050085 {
Ed Tanousac106bf2023-06-07 09:24:59 -070086 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050087 "Enabled";
88 }
89 }
90}
91
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093 * @brief Update "ProcessorSummary" "Status" "State" based on
94 * CPU Functional State
95 *
Ed Tanousac106bf2023-06-07 09:24:59 -070096 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050097 * @param[in] cpuFunctionalState is CPU functional true/false
98 *
99 * @return None.
100 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700101inline void modifyCpuFunctionalState(
102 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103{
Ed Tanous62598e32023-07-17 17:06:25 -0700104 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500105
Ed Tanous02cad962022-06-30 16:50:15 -0700106 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700107 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500109 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110 // Update STATE only if previous State was Non_Functional and current CPU is
111 // Functional.
112 if (prevProcState == "Disabled")
113 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800114 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500115 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700116 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500117 "Enabled";
118 }
119 }
120}
121
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500122/*
123 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
124 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700125 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500126 * @param[in] cpuPresenceState CPU present or not
127 *
128 * @return None.
129 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400130inline void modifyCpuPresenceState(
131 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuPresent)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500132{
Ed Tanous62598e32023-07-17 17:06:25 -0700133 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500134
135 if (isCpuPresent)
136 {
137 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700138 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500139 auto* procCountPtr =
140 procCount.get_ptr<nlohmann::json::number_integer_t*>();
141 if (procCountPtr != nullptr)
142 {
143 // shouldn't be possible to be nullptr
144 *procCountPtr += 1;
145 }
146 }
147}
148
Ali Ahmed382d6472021-09-03 16:53:53 -0500149inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700150 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500151 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
152 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153{
Ed Tanous62598e32023-07-17 17:06:25 -0700154 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500155
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200156 // TODO: Get Model
157
158 const uint16_t* coreCount = nullptr;
159
160 const bool success = sdbusplus::unpackPropertiesNoThrow(
161 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
162
163 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500164 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700165 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200166 return;
167 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500168
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200169 if (coreCount != nullptr)
170 {
171 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700172 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200173 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500174
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200175 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500176 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200177 coreCountJson = *coreCount;
178 }
179 else
180 {
181 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500182 }
183 }
184}
185
186/*
187 * @brief Get ProcessorSummary fields
188 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700189 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500190 * @param[in] service dbus service for Cpu Information
191 * @param[in] path dbus path for Cpu
192 *
193 * @return None.
194 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700195inline void
196 getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
197 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500198{
Ed Tanousac106bf2023-06-07 09:24:59 -0700199 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
200 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500201 if (ec3)
202 {
Ed Tanous62598e32023-07-17 17:06:25 -0700203 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500204 return;
205 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700206 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500207 };
208
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500209 // Get the Presence of CPU
Ed Tanousdeae6a72024-11-11 21:58:57 -0800210 dbus::utility::getProperty<bool>(*crow::connections::systemBus, service,
211 path, "xyz.openbmc_project.Inventory.Item",
212 "Present", std::move(getCpuPresenceState));
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500213
Ed Tanousdeae6a72024-11-11 21:58:57 -0800214 dbus::utility::getAllProperties(
215 service, path, "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700216 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800217 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800218 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400219 if (ec2)
220 {
221 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
222 messages::internalError(asyncResp->res);
223 return;
224 }
225 getProcessorProperties(asyncResp, properties);
226 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500227}
228
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500229/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500230 * @brief processMemoryProperties fields
231 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700232 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500233 * @param[in] DBUS properties for memory
234 *
235 * @return None.
236 */
237inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700238 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500239 const dbus::utility::DBusPropertiesMap& properties)
240{
Ed Tanous62598e32023-07-17 17:06:25 -0700241 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500242
243 if (properties.empty())
244 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500245 return;
246 }
247
248 const size_t* memorySizeInKB = nullptr;
249
250 const bool success = sdbusplus::unpackPropertiesNoThrow(
251 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
252 memorySizeInKB);
253
254 if (!success)
255 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700256 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500257 return;
258 }
259
260 if (memorySizeInKB != nullptr)
261 {
262 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700263 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500264 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500265 if (preValue == nullptr)
266 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700267 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500268 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500269 }
270 else
271 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700272 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500273 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
274 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500275 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500276 }
277}
278
279/*
280 * @brief Get getMemorySummary fields
281 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700282 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500283 * @param[in] service dbus service for memory Information
284 * @param[in] path dbus path for memory
285 *
286 * @return None.
287 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700288inline void
289 getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
290 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500291{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800292 dbus::utility::getAllProperties(
293 service, path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700294 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500295 path](const boost::system::error_code& ec2,
296 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400297 if (ec2)
298 {
299 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
300 messages::internalError(asyncResp->res);
301 return;
302 }
303 processMemoryProperties(asyncResp, properties);
304 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500305}
306
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500307inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
308 const boost::system::error_code& ec,
309 const dbus::utility::DBusPropertiesMap& properties)
310{
311 if (ec)
312 {
313 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
314 messages::internalError(asyncResp->res);
315 return;
316 }
317 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
318
319 const std::string* uUID = nullptr;
320
321 const bool success = sdbusplus::unpackPropertiesNoThrow(
322 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
323
324 if (!success)
325 {
326 messages::internalError(asyncResp->res);
327 return;
328 }
329
330 if (uUID != nullptr)
331 {
332 std::string valueStr = *uUID;
333 if (valueStr.size() == 32)
334 {
335 valueStr.insert(8, 1, '-');
336 valueStr.insert(13, 1, '-');
337 valueStr.insert(18, 1, '-');
338 valueStr.insert(23, 1, '-');
339 }
340 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
341 asyncResp->res.jsonValue["UUID"] = valueStr;
342 }
343}
344
345inline void
346 afterGetInventory(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
347 const boost::system::error_code& ec,
348 const dbus::utility::DBusPropertiesMap& propertiesList)
349{
350 if (ec)
351 {
352 // doesn't have to include this
353 // interface
354 return;
355 }
356 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
357
358 const std::string* partNumber = nullptr;
359 const std::string* serialNumber = nullptr;
360 const std::string* manufacturer = nullptr;
361 const std::string* model = nullptr;
362 const std::string* subModel = nullptr;
363
364 const bool success = sdbusplus::unpackPropertiesNoThrow(
365 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
366 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
367 "Model", model, "SubModel", subModel);
368
369 if (!success)
370 {
371 messages::internalError(asyncResp->res);
372 return;
373 }
374
375 if (partNumber != nullptr)
376 {
377 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
378 }
379
380 if (serialNumber != nullptr)
381 {
382 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
383 }
384
385 if (manufacturer != nullptr)
386 {
387 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
388 }
389
390 if (model != nullptr)
391 {
392 asyncResp->res.jsonValue["Model"] = *model;
393 }
394
395 if (subModel != nullptr)
396 {
397 asyncResp->res.jsonValue["SubModel"] = *subModel;
398 }
399
400 // Grab the bios version
401 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
402 "BiosVersion", false);
403}
404
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400405inline void afterGetAssetTag(
406 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
407 const boost::system::error_code& ec, const std::string& value)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500408{
409 if (ec)
410 {
411 // doesn't have to include this
412 // interface
413 return;
414 }
415
416 asyncResp->res.jsonValue["AssetTag"] = value;
417}
418
419inline void afterSystemGetSubTree(
420 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500421 const boost::system::error_code& ec,
422 const dbus::utility::MapperGetSubTreeResponse& subtree)
423{
424 if (ec)
425 {
426 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
427 messages::internalError(asyncResp->res);
428 return;
429 }
430 // Iterate over all retrieved ObjectPaths.
431 for (const std::pair<
432 std::string,
433 std::vector<std::pair<std::string, std::vector<std::string>>>>&
434 object : subtree)
435 {
436 const std::string& path = object.first;
437 BMCWEB_LOG_DEBUG("Got path: {}", path);
438 const std::vector<std::pair<std::string, std::vector<std::string>>>&
439 connectionNames = object.second;
440 if (connectionNames.empty())
441 {
442 continue;
443 }
444
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500445 // This is not system, so check if it's cpu, dimm, UUID or
446 // BiosVer
447 for (const auto& connection : connectionNames)
448 {
449 for (const auto& interfaceName : connection.second)
450 {
451 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
452 {
453 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
454
455 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500456 }
457 else if (interfaceName ==
458 "xyz.openbmc_project.Inventory.Item.Cpu")
459 {
460 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
461
462 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500463 }
464 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
465 {
466 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
467
Ed Tanousdeae6a72024-11-11 21:58:57 -0800468 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500469 *crow::connections::systemBus, connection.first, path,
470 "xyz.openbmc_project.Common.UUID",
471 [asyncResp](const boost::system::error_code& ec3,
472 const dbus::utility::DBusPropertiesMap&
473 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400474 afterGetUUID(asyncResp, ec3, properties);
475 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500476 }
477 else if (interfaceName ==
478 "xyz.openbmc_project.Inventory.Item.System")
479 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800480 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500481 *crow::connections::systemBus, connection.first, path,
482 "xyz.openbmc_project.Inventory.Decorator.Asset",
483 [asyncResp](const boost::system::error_code& ec3,
484 const dbus::utility::DBusPropertiesMap&
485 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400486 afterGetInventory(asyncResp, ec3, properties);
487 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500488
Ed Tanousdeae6a72024-11-11 21:58:57 -0800489 dbus::utility::getProperty<std::string>(
490 connection.first, path,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500491 "xyz.openbmc_project.Inventory.Decorator."
492 "AssetTag",
493 "AssetTag",
494 std::bind_front(afterGetAssetTag, asyncResp));
495 }
496 }
497 }
498 }
499}
500
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500501/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700502 * @brief Retrieves computer system properties over dbus
503 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700504 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700505 *
506 * @return None.
507 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700508inline void
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500509 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700510{
Ed Tanous62598e32023-07-17 17:06:25 -0700511 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800512 constexpr std::array<std::string_view, 5> interfaces = {
513 "xyz.openbmc_project.Inventory.Decorator.Asset",
514 "xyz.openbmc_project.Inventory.Item.Cpu",
515 "xyz.openbmc_project.Inventory.Item.Dimm",
516 "xyz.openbmc_project.Inventory.Item.System",
517 "xyz.openbmc_project.Common.UUID",
518 };
519 dbus::utility::getSubTree(
520 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500521 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700522}
523
524/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700525 * @brief Retrieves host state properties over dbus
526 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700527 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Ed Tanous6c34de42018-08-29 13:37:36 -0700528 *
529 * @return None.
530 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700531inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700532{
Ed Tanous62598e32023-07-17 17:06:25 -0700533 BMCWEB_LOG_DEBUG("Get host information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800534 dbus::utility::getProperty<std::string>(
535 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
536 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700537 [asyncResp](const boost::system::error_code& ec,
538 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400539 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400541 if (ec == boost::system::errc::host_unreachable)
542 {
543 // Service not available, no error, just don't return
544 // host state info
545 BMCWEB_LOG_DEBUG("Service not available {}", ec);
546 return;
547 }
548 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
549 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700550 return;
551 }
Ed Tanous66173382018-08-15 18:20:59 -0700552
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400553 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
554 // Verify Host State
555 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
556 {
557 asyncResp->res.jsonValue["PowerState"] =
558 resource::PowerState::On;
559 asyncResp->res.jsonValue["Status"]["State"] =
560 resource::State::Enabled;
561 }
562 else if (hostState ==
563 "xyz.openbmc_project.State.Host.HostState.Quiesced")
564 {
565 asyncResp->res.jsonValue["PowerState"] =
566 resource::PowerState::On;
567 asyncResp->res.jsonValue["Status"]["State"] =
568 resource::State::Quiesced;
569 }
570 else if (hostState ==
571 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
572 {
573 asyncResp->res.jsonValue["PowerState"] =
574 resource::PowerState::On;
575 asyncResp->res.jsonValue["Status"]["State"] =
576 resource::State::InTest;
577 }
578 else if (
579 hostState ==
580 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
581 {
582 asyncResp->res.jsonValue["PowerState"] =
583 resource::PowerState::PoweringOn;
584 asyncResp->res.jsonValue["Status"]["State"] =
585 resource::State::Starting;
586 }
587 else if (
588 hostState ==
589 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
590 {
591 asyncResp->res.jsonValue["PowerState"] =
592 resource::PowerState::PoweringOff;
593 asyncResp->res.jsonValue["Status"]["State"] =
594 resource::State::Disabled;
595 }
596 else
597 {
598 asyncResp->res.jsonValue["PowerState"] =
599 resource::PowerState::Off;
600 asyncResp->res.jsonValue["Status"]["State"] =
601 resource::State::Disabled;
602 }
603 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700604}
605
606/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500607 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530608 *
609 * @param[in] dbusSource The boot source in DBUS speak.
610 *
611 * @return Returns as a string, the boot source in Redfish terms. If translation
612 * cannot be done, returns an empty string.
613 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000614inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615{
616 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
617 {
618 return "None";
619 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700620 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530621 {
622 return "Hdd";
623 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700624 if (dbusSource ==
625 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530626 {
627 return "Cd";
628 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700629 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 {
631 return "Pxe";
632 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700633 if (dbusSource ==
634 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700635 {
636 return "Usb";
637 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700638 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530639}
640
641/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300642 * @brief Translates boot type DBUS property value to redfish.
643 *
644 * @param[in] dbusType The boot type in DBUS speak.
645 *
646 * @return Returns as a string, the boot type in Redfish terms. If translation
647 * cannot be done, returns an empty string.
648 */
649inline std::string dbusToRfBootType(const std::string& dbusType)
650{
651 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
652 {
653 return "Legacy";
654 }
655 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
656 {
657 return "UEFI";
658 }
659 return "";
660}
661
662/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500663 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530664 *
665 * @param[in] dbusMode The boot mode in DBUS speak.
666 *
667 * @return Returns as a string, the boot mode in Redfish terms. If translation
668 * cannot be done, returns an empty string.
669 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000670inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530671{
672 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
673 {
674 return "None";
675 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700676 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530677 {
678 return "Diags";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "BiosSetup";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685}
686
687/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600688 * @brief Translates boot progress DBUS property value to redfish.
689 *
690 * @param[in] dbusBootProgress The boot progress in DBUS speak.
691 *
692 * @return Returns as a string, the boot progress in Redfish terms. If
693 * translation cannot be done, returns "None".
694 */
695inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
696{
697 // Now convert the D-Bus BootProgress to the appropriate Redfish
698 // enum
699 std::string rfBpLastState = "None";
700 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
701 "ProgressStages.Unspecified")
702 {
703 rfBpLastState = "None";
704 }
705 else if (dbusBootProgress ==
706 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
707 "PrimaryProcInit")
708 {
709 rfBpLastState = "PrimaryProcessorInitializationStarted";
710 }
711 else if (dbusBootProgress ==
712 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
713 "BusInit")
714 {
715 rfBpLastState = "BusInitializationStarted";
716 }
717 else if (dbusBootProgress ==
718 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
719 "MemoryInit")
720 {
721 rfBpLastState = "MemoryInitializationStarted";
722 }
723 else if (dbusBootProgress ==
724 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
725 "SecondaryProcInit")
726 {
727 rfBpLastState = "SecondaryProcessorInitializationStarted";
728 }
729 else if (dbusBootProgress ==
730 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
731 "PCIInit")
732 {
733 rfBpLastState = "PCIResourceConfigStarted";
734 }
735 else if (dbusBootProgress ==
736 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
737 "SystemSetup")
738 {
739 rfBpLastState = "SetupEntered";
740 }
741 else if (dbusBootProgress ==
742 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
743 "SystemInitComplete")
744 {
745 rfBpLastState = "SystemHardwareInitializationComplete";
746 }
747 else if (dbusBootProgress ==
748 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
749 "OSStart")
750 {
751 rfBpLastState = "OSBootStarted";
752 }
753 else if (dbusBootProgress ==
754 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
755 "OSRunning")
756 {
757 rfBpLastState = "OSRunning";
758 }
759 else
760 {
Ed Tanous62598e32023-07-17 17:06:25 -0700761 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600762 // Just return the default
763 }
764 return rfBpLastState;
765}
766
767/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500768 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530769 *
770 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700771 * @param[out] bootSource The DBus source
772 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700774 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530775 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400776inline int assignBootParameters(
777 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
778 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530779{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300780 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
781 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700782
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530783 if (rfSource == "None")
784 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700785 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530786 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700787 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700789 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
790 }
791 else if (rfSource == "Hdd")
792 {
793 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
794 }
795 else if (rfSource == "Diags")
796 {
797 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
798 }
799 else if (rfSource == "Cd")
800 {
801 bootSource =
802 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
803 }
804 else if (rfSource == "BiosSetup")
805 {
806 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530807 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700808 else if (rfSource == "Usb")
809 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700810 bootSource =
811 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700812 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530813 else
814 {
Ed Tanous62598e32023-07-17 17:06:25 -0700815 BMCWEB_LOG_DEBUG(
816 "Invalid property value for BootSourceOverrideTarget: {}",
817 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700818 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700819 "BootSourceTargetOverride");
820 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530821 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700822 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530823}
Ali Ahmed19817712021-06-29 17:01:52 -0500824
Andrew Geissler978b8802020-11-19 13:36:40 -0600825/**
826 * @brief Retrieves boot progress of the system
827 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700828 * @param[in] asyncResp Shared pointer for generating response message.
Andrew Geissler978b8802020-11-19 13:36:40 -0600829 *
830 * @return None.
831 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700832inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600833{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800834 dbus::utility::getProperty<std::string>(
835 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700836 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700837 [asyncResp](const boost::system::error_code& ec,
838 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400839 if (ec)
840 {
841 // BootProgress is an optional object so just do nothing if
842 // not found
843 return;
844 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600845
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400846 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600847
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400848 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
849 dbusToRfBootProgress(bootProgressStr);
850 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600851}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530852
853/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000854 * @brief Retrieves boot progress Last Update of the system
855 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700856 * @param[in] asyncResp Shared pointer for generating response message.
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000857 *
858 * @return None.
859 */
860inline void getBootProgressLastStateTime(
Ed Tanousac106bf2023-06-07 09:24:59 -0700861 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000862{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800863 dbus::utility::getProperty<uint64_t>(
864 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000865 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700866 [asyncResp](const boost::system::error_code& ec,
867 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400868 if (ec)
869 {
870 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
871 return;
872 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000873
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400874 // BootProgressLastUpdate is the last time the BootProgress property
875 // was updated. The time is the Epoch time, number of microseconds
876 // since 1 Jan 1970 00::00::00 UTC."
877 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
878 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000879
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400880 // Convert to ISO 8601 standard
881 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
882 redfish::time_utils::getDateTimeUintUs(lastStateTime);
883 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000884}
885
886/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300887 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300888 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700889 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300890 *
891 * @return None.
892 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300893
Ed Tanousac106bf2023-06-07 09:24:59 -0700894inline void
895 getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300896{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800897 dbus::utility::getProperty<std::string>(
898 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700899 "/xyz/openbmc_project/control/host0/boot",
900 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700901 [asyncResp](const boost::system::error_code& ec,
902 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400903 if (ec)
904 {
905 // not an error, don't have to have the interface
906 return;
907 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300908
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400909 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300910
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400911 asyncResp->res
912 .jsonValue["Boot"]
913 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
914 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300915
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400916 auto rfType = dbusToRfBootType(bootType);
917 if (rfType.empty())
918 {
919 messages::internalError(asyncResp->res);
920 return;
921 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300922
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400923 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
924 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300925}
926
927/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300928 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530929 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700930 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530931 *
932 * @return None.
933 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300934
Ed Tanousac106bf2023-06-07 09:24:59 -0700935inline void
936 getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530937{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800938 dbus::utility::getProperty<std::string>(
939 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700940 "/xyz/openbmc_project/control/host0/boot",
941 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700942 [asyncResp](const boost::system::error_code& ec,
943 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400944 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530945 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400946 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
947 messages::internalError(asyncResp->res);
948 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530949 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400950
951 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
952
953 nlohmann::json::array_t allowed;
954 allowed.emplace_back("None");
955 allowed.emplace_back("Pxe");
956 allowed.emplace_back("Hdd");
957 allowed.emplace_back("Cd");
958 allowed.emplace_back("Diags");
959 allowed.emplace_back("BiosSetup");
960 allowed.emplace_back("Usb");
961
962 asyncResp->res
963 .jsonValue["Boot"]
964 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
965 std::move(allowed);
966 if (bootModeStr !=
967 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
968 {
969 auto rfMode = dbusToRfBootMode(bootModeStr);
970 if (!rfMode.empty())
971 {
972 asyncResp->res
973 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
974 }
975 }
976 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530977}
978
979/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300980 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530981 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700982 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530983 *
984 * @return None.
985 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300986
987inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700988 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530989{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800990 dbus::utility::getProperty<std::string>(
991 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700992 "/xyz/openbmc_project/control/host0/boot",
993 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanousac106bf2023-06-07 09:24:59 -0700994 [asyncResp](const boost::system::error_code& ec,
995 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400996 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +0000997 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400998 if (ec.value() == boost::asio::error::host_unreachable)
999 {
1000 return;
1001 }
1002 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1003 messages::internalError(asyncResp->res);
Nan Zhou5ef735c2022-06-22 05:24:21 +00001004 return;
1005 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301006
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001007 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001009 auto rfSource = dbusToRfBootSource(bootSourceStr);
1010 if (!rfSource.empty())
1011 {
1012 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1013 rfSource;
1014 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001015
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001016 // Get BootMode as BootSourceOverrideTarget is constructed
1017 // from both BootSource and BootMode
1018 getBootOverrideMode(asyncResp);
1019 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301020}
1021
1022/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001023 * @brief This functions abstracts all the logic behind getting a
1024 * "BootSourceOverrideEnabled" property from an overall boot override enable
1025 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001027 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301028 *
1029 * @return None.
1030 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301031
Ed Tanousac106bf2023-06-07 09:24:59 -07001032inline void processBootOverrideEnable(
1033 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1034 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001035{
1036 if (!bootOverrideEnableSetting)
1037 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001038 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1039 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001040 return;
1041 }
1042
1043 // If boot source override is enabled, we need to check 'one_time'
1044 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001045 dbus::utility::getProperty<bool>(
1046 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001047 "/xyz/openbmc_project/control/host0/boot/one_time",
1048 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001049 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001050 if (ec)
1051 {
1052 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1053 messages::internalError(asyncResp->res);
1054 return;
1055 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301056
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001057 if (oneTimeSetting)
1058 {
1059 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1060 "Once";
1061 }
1062 else
1063 {
1064 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1065 "Continuous";
1066 }
1067 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301068}
1069
1070/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001071 * @brief Retrieves boot override enable over DBUS
1072 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001073 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074 *
1075 * @return None.
1076 */
1077
1078inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001079 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001080{
Ed Tanousdeae6a72024-11-11 21:58:57 -08001081 dbus::utility::getProperty<bool>(
1082 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001083 "/xyz/openbmc_project/control/host0/boot",
1084 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001085 [asyncResp](const boost::system::error_code& ec,
1086 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001087 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001088 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001089 if (ec.value() == boost::asio::error::host_unreachable)
1090 {
1091 return;
1092 }
1093 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1094 messages::internalError(asyncResp->res);
Nan Zhou5ef735c2022-06-22 05:24:21 +00001095 return;
1096 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001097
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001098 processBootOverrideEnable(asyncResp, bootOverrideEnable);
1099 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001100}
1101
1102/**
1103 * @brief Retrieves boot source override properties
1104 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001105 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001106 *
1107 * @return None.
1108 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001109inline void
1110 getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001111{
Ed Tanous62598e32023-07-17 17:06:25 -07001112 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001113
Ed Tanousac106bf2023-06-07 09:24:59 -07001114 getBootOverrideSource(asyncResp);
1115 getBootOverrideType(asyncResp);
1116 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001117}
1118
1119/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001120 * @brief Retrieves the Last Reset Time
1121 *
1122 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1123 * and power off. Even though this is the "system" Redfish object look at the
1124 * chassis D-Bus interface for the LastStateChangeTime since this has the
1125 * last power operation time.
1126 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001127 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001128 *
1129 * @return None.
1130 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001131inline void
1132 getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001133{
Ed Tanous62598e32023-07-17 17:06:25 -07001134 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001135
Ed Tanousdeae6a72024-11-11 21:58:57 -08001136 dbus::utility::getProperty<uint64_t>(
1137 "xyz.openbmc_project.State.Chassis",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001138 "/xyz/openbmc_project/state/chassis0",
1139 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001140 [asyncResp](const boost::system::error_code& ec,
1141 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001142 if (ec)
1143 {
1144 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1145 return;
1146 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001147
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001148 // LastStateChangeTime is epoch time, in milliseconds
1149 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1150 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001151
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001152 // Convert to ISO 8601 standard
1153 asyncResp->res.jsonValue["LastResetTime"] =
1154 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1155 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001156}
1157
1158/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001159 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1160 *
1161 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1162 * corresponding property "AttemptsLeft" that keeps track of the amount of
1163 * automatic retry attempts left are hosted in phosphor-state-manager through
1164 * dbus.
1165 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001166 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001167 *
1168 * @return None.
1169 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001170inline void getAutomaticRebootAttempts(
1171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001172{
Ed Tanous62598e32023-07-17 17:06:25 -07001173 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001174
Ed Tanousdeae6a72024-11-11 21:58:57 -08001175 dbus::utility::getAllProperties(
1176 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Corey Hardesty797d5da2022-04-26 17:54:52 +08001177 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001178 [asyncResp{asyncResp}](
1179 const boost::system::error_code& ec,
1180 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001181 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001182 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001183 if (ec.value() != EBADR)
1184 {
1185 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1186 messages::internalError(asyncResp->res);
1187 }
1188 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001189 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001190
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001191 const uint32_t* attemptsLeft = nullptr;
1192 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001193
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001194 const bool success = sdbusplus::unpackPropertiesNoThrow(
1195 dbus_utils::UnpackErrorPrinter(), propertiesList,
1196 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001197
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001198 if (!success)
1199 {
1200 messages::internalError(asyncResp->res);
1201 return;
1202 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001203
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001204 if (attemptsLeft != nullptr)
1205 {
1206 asyncResp->res
1207 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1208 *attemptsLeft;
1209 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001210
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001211 if (retryAttempts != nullptr)
1212 {
1213 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1214 *retryAttempts;
1215 }
1216 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001217}
1218
1219/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001220 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1221 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001222 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001223 *
1224 * @return None.
1225 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001226inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001227 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001228{
Ed Tanous62598e32023-07-17 17:06:25 -07001229 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001230
Ed Tanousdeae6a72024-11-11 21:58:57 -08001231 dbus::utility::getProperty<bool>(
1232 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001233 "/xyz/openbmc_project/control/host0/auto_reboot",
1234 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001235 [asyncResp](const boost::system::error_code& ec,
1236 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001237 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001238 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001239 if (ec.value() != EBADR)
1240 {
1241 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1242 messages::internalError(asyncResp->res);
1243 }
1244 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001245 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001246
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001247 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1248 if (autoRebootEnabled)
1249 {
1250 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1251 "RetryAttempts";
1252 }
1253 else
1254 {
1255 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1256 "Disabled";
1257 }
1258 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001259
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001260 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1261 // and RetryAttempts. OpenBMC only supports Disabled and
1262 // RetryAttempts.
1263 nlohmann::json::array_t allowed;
1264 allowed.emplace_back("Disabled");
1265 allowed.emplace_back("RetryAttempts");
1266 asyncResp->res
1267 .jsonValue["Boot"]
1268 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1269 std::move(allowed);
1270 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001271}
1272
1273/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001274 * @brief Sets RetryAttempts
1275 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001276 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001277 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1278 *
1279 *@return None.
1280 */
1281
Ed Tanousac106bf2023-06-07 09:24:59 -07001282inline void setAutomaticRetryAttempts(
1283 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1284 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001285{
Ed Tanous62598e32023-07-17 17:06:25 -07001286 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001287 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301288 asyncResp, "Boot/AutomaticRetryAttempts",
1289 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001290 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001291 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301292 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001293}
1294
Ed Tanous8d69c662023-06-21 10:29:06 -07001295inline computer_system::PowerRestorePolicyTypes
1296 redfishPowerRestorePolicyFromDbus(std::string_view value)
1297{
1298 if (value ==
1299 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1300 {
1301 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1302 }
1303 if (value ==
1304 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1305 {
1306 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1307 }
1308 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001309 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001310 {
1311 return computer_system::PowerRestorePolicyTypes::LastState;
1312 }
1313 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1314 {
1315 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1316 }
1317 return computer_system::PowerRestorePolicyTypes::Invalid;
1318}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001319/**
George Liuc6a620f2020-04-10 17:18:11 +08001320 * @brief Retrieves power restore policy over DBUS.
1321 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001322 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001323 *
1324 * @return None.
1325 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001326inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001327 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001328{
Ed Tanous62598e32023-07-17 17:06:25 -07001329 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001330
Ed Tanousdeae6a72024-11-11 21:58:57 -08001331 dbus::utility::getProperty<std::string>(
1332 "xyz.openbmc_project.Settings",
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001333 "/xyz/openbmc_project/control/host0/power_restore_policy",
1334 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001335 [asyncResp](const boost::system::error_code& ec,
1336 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001337 if (ec)
1338 {
1339 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1340 return;
1341 }
1342 computer_system::PowerRestorePolicyTypes restore =
1343 redfishPowerRestorePolicyFromDbus(policy);
1344 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1345 {
1346 messages::internalError(asyncResp->res);
1347 return;
1348 }
George Liuc6a620f2020-04-10 17:18:11 +08001349
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001350 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1351 });
George Liuc6a620f2020-04-10 17:18:11 +08001352}
1353
1354/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001355 * @brief Stop Boot On Fault over DBUS.
1356 *
1357 * @param[in] asyncResp Shared pointer for generating response message.
1358 *
1359 * @return None.
1360 */
1361inline void
1362 getStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1363{
Ed Tanous62598e32023-07-17 17:06:25 -07001364 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001365
Ed Tanousdeae6a72024-11-11 21:58:57 -08001366 dbus::utility::getProperty<bool>(
1367 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001368 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1369 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001370 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001371 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001372 if (ec.value() != EBADR)
1373 {
1374 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1375 messages::internalError(asyncResp->res);
1376 }
1377 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001378 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001379
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001380 if (value)
1381 {
1382 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1383 computer_system::StopBootOnFault::AnyFault;
1384 }
1385 else
1386 {
1387 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1388 computer_system::StopBootOnFault::Never;
1389 }
1390 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001391}
1392
1393/**
Ali Ahmed19817712021-06-29 17:01:52 -05001394 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1395 * TPM is required for booting the host.
1396 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001397 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001398 *
1399 * @return None.
1400 */
1401inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001402 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001403{
Ed Tanous62598e32023-07-17 17:06:25 -07001404 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001405 constexpr std::array<std::string_view, 1> interfaces = {
1406 "xyz.openbmc_project.Control.TPM.Policy"};
1407 dbus::utility::getSubTree(
1408 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001409 [asyncResp](const boost::system::error_code& ec,
1410 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001411 if (ec)
Ali Ahmed19817712021-06-29 17:01:52 -05001412 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001413 BMCWEB_LOG_DEBUG(
1414 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1415 // This is an optional D-Bus object so just return if
1416 // error occurs
1417 return;
1418 }
1419 if (subtree.empty())
1420 {
1421 // As noted above, this is an optional interface so just return
1422 // if there is no instance found
1423 return;
1424 }
1425
1426 /* When there is more than one TPMEnable object... */
1427 if (subtree.size() > 1)
1428 {
1429 BMCWEB_LOG_DEBUG(
1430 "DBUS response has more than 1 TPM Enable object:{}",
1431 subtree.size());
1432 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001433 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001434 return;
1435 }
1436
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001437 // Make sure the Dbus response map has a service and objectPath
1438 // field
1439 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
Ali Ahmed19817712021-06-29 17:01:52 -05001440 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001441 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1442 messages::internalError(asyncResp->res);
1443 return;
Ali Ahmed19817712021-06-29 17:01:52 -05001444 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001445
1446 const std::string& path = subtree[0].first;
1447 const std::string& serv = subtree[0].second.begin()->first;
1448
1449 // Valid TPM Enable object found, now reading the current value
Ed Tanousdeae6a72024-11-11 21:58:57 -08001450 dbus::utility::getProperty<bool>(
1451 serv, path, "xyz.openbmc_project.Control.TPM.Policy",
1452 "TPMEnable",
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001453 [asyncResp](const boost::system::error_code& ec2,
1454 bool tpmRequired) {
1455 if (ec2)
1456 {
1457 BMCWEB_LOG_ERROR(
1458 "D-BUS response error on TPM.Policy Get{}", ec2);
1459 messages::internalError(asyncResp->res);
1460 return;
1461 }
1462
1463 if (tpmRequired)
1464 {
1465 asyncResp->res
1466 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1467 "Required";
1468 }
1469 else
1470 {
1471 asyncResp->res
1472 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1473 "Disabled";
1474 }
1475 });
George Liue99073f2022-12-09 11:06:16 +08001476 });
Ali Ahmed19817712021-06-29 17:01:52 -05001477}
1478
1479/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001480 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1481 * TPM is required for booting the host.
1482 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001483 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001484 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1485 *
1486 * @return None.
1487 */
1488inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001489 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001490{
Ed Tanous62598e32023-07-17 17:06:25 -07001491 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001492 constexpr std::array<std::string_view, 1> interfaces = {
1493 "xyz.openbmc_project.Control.TPM.Policy"};
1494 dbus::utility::getSubTree(
1495 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001496 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001497 tpmRequired](const boost::system::error_code& ec,
1498 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001499 if (ec)
1500 {
1501 BMCWEB_LOG_ERROR(
1502 "DBUS response error on TPM.Policy GetSubTree{}", ec);
1503 messages::internalError(asyncResp->res);
1504 return;
1505 }
1506 if (subtree.empty())
1507 {
1508 messages::propertyValueNotInList(asyncResp->res,
1509 "ComputerSystem",
1510 "TrustedModuleRequiredToBoot");
1511 return;
1512 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001513
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001514 /* When there is more than one TPMEnable object... */
1515 if (subtree.size() > 1)
1516 {
1517 BMCWEB_LOG_DEBUG(
1518 "DBUS response has more than 1 TPM Enable object:{}",
1519 subtree.size());
1520 // Throw an internal Error and return
1521 messages::internalError(asyncResp->res);
1522 return;
1523 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001524
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001525 // Make sure the Dbus response map has a service and objectPath
1526 // field
1527 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1528 {
1529 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1530 messages::internalError(asyncResp->res);
1531 return;
1532 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001533
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001534 const std::string& path = subtree[0].first;
1535 const std::string& serv = subtree[0].second.begin()->first;
Ed Tanous002d39b2022-05-31 08:59:27 -07001536
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001537 if (serv.empty())
1538 {
1539 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1540 messages::internalError(asyncResp->res);
1541 return;
1542 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001543
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001544 // Valid TPM Enable object found, now setting the value
1545 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1546 path, "xyz.openbmc_project.Control.TPM.Policy",
1547 "TPMEnable", tpmRequired);
1548 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001549}
1550
1551/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301552 * @brief Sets boot properties into DBUS object(s).
1553 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001554 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001555 * @param[in] bootType The boot type to set.
1556 * @return Integer error code.
1557 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001558inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001559 const std::optional<std::string>& bootType)
1560{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001561 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001562
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001563 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001564 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001565 return;
1566 }
1567
1568 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001569 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001570 // Figure out which DBUS interface and property to use
1571 if (*bootType == "Legacy")
1572 {
1573 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1574 }
1575 else if (*bootType == "UEFI")
1576 {
1577 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1578 }
1579 else
1580 {
Ed Tanous62598e32023-07-17 17:06:25 -07001581 BMCWEB_LOG_DEBUG("Invalid property value for "
1582 "BootSourceOverrideMode: {}",
1583 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001584 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001585 "BootSourceOverrideMode");
1586 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001587 }
1588
1589 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001590 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001591
Ginu Georgee93abac2024-06-14 17:35:27 +05301592 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1593 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001594 sdbusplus::message::object_path(
1595 "/xyz/openbmc_project/control/host0/boot"),
1596 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301597 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001598}
1599
1600/**
1601 * @brief Sets boot properties into DBUS object(s).
1602 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001603 * @param[in] asyncResp Shared pointer for generating response
1604 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001605 * @param[in] bootType The boot type to set.
1606 * @return Integer error code.
1607 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001608inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001609 const std::optional<std::string>& bootEnable)
1610{
1611 if (!bootEnable)
1612 {
1613 return;
1614 }
1615 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001616 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001617
1618 bool bootOverrideEnable = false;
1619 bool bootOverridePersistent = false;
1620 // Figure out which DBUS interface and property to use
1621 if (*bootEnable == "Disabled")
1622 {
1623 bootOverrideEnable = false;
1624 }
1625 else if (*bootEnable == "Once")
1626 {
1627 bootOverrideEnable = true;
1628 bootOverridePersistent = false;
1629 }
1630 else if (*bootEnable == "Continuous")
1631 {
1632 bootOverrideEnable = true;
1633 bootOverridePersistent = true;
1634 }
1635 else
1636 {
Ed Tanous62598e32023-07-17 17:06:25 -07001637 BMCWEB_LOG_DEBUG(
1638 "Invalid property value for BootSourceOverrideEnabled: {}",
1639 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001640 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001641 "BootSourceOverrideEnabled");
1642 return;
1643 }
1644
1645 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001646 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001647
Ginu Georgee93abac2024-06-14 17:35:27 +05301648 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1649 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001650 sdbusplus::message::object_path(
1651 "/xyz/openbmc_project/control/host0/boot"),
1652 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301653 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001654
1655 if (!bootOverrideEnable)
1656 {
1657 return;
1658 }
1659
1660 // In case boot override is enabled we need to set correct value for the
1661 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001662 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1663 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001664
Ginu Georgee93abac2024-06-14 17:35:27 +05301665 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1666 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001667 sdbusplus::message::object_path(
1668 "/xyz/openbmc_project/control/host0/boot/one_time"),
1669 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301670 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +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 message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301677 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301678 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001679 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301680 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001681inline void
1682 setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1683 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301684{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001685 std::string bootSourceStr;
1686 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001687
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001688 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301689 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690 return;
1691 }
1692
1693 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001694 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001695 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001696 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1697 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001698 {
Ed Tanous62598e32023-07-17 17:06:25 -07001699 BMCWEB_LOG_DEBUG(
1700 "Invalid property value for BootSourceOverrideTarget: {}",
1701 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001702 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001703 "BootSourceTargetOverride");
1704 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001705 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301706
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001707 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001708 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1709 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001710
Ginu Georgee93abac2024-06-14 17:35:27 +05301711 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1712 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001713 sdbusplus::message::object_path(
1714 "/xyz/openbmc_project/control/host0/boot"),
1715 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301716 bootSourceStr);
1717 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1718 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001719 sdbusplus::message::object_path(
1720 "/xyz/openbmc_project/control/host0/boot"),
1721 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301722 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001723}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001724
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001725/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001726 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301727 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001728 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301729 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001730 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301731 * @param[in] bootEnable The boot override enable from incoming RF request.
1732 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001733 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301734 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001735
Ed Tanousac106bf2023-06-07 09:24:59 -07001736inline void
1737 setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1738 const std::optional<std::string>& bootSource,
1739 const std::optional<std::string>& bootType,
1740 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301741{
Ed Tanous62598e32023-07-17 17:06:25 -07001742 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301743
Ed Tanousac106bf2023-06-07 09:24:59 -07001744 setBootModeOrSource(asyncResp, bootSource);
1745 setBootType(asyncResp, bootType);
1746 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301747}
1748
George Liuc6a620f2020-04-10 17:18:11 +08001749/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001750 * @brief Sets AssetTag
1751 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001752 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001753 * @param[in] assetTag "AssetTag" from request.
1754 *
1755 * @return None.
1756 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001757inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001758 const std::string& assetTag)
1759{
George Liue99073f2022-12-09 11:06:16 +08001760 constexpr std::array<std::string_view, 1> interfaces = {
1761 "xyz.openbmc_project.Inventory.Item.System"};
1762 dbus::utility::getSubTree(
1763 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001764 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001765 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001766 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001767 if (ec)
1768 {
1769 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1770 messages::internalError(asyncResp->res);
1771 return;
1772 }
1773 if (subtree.empty())
1774 {
1775 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1776 messages::internalError(asyncResp->res);
1777 return;
1778 }
1779 // Assume only 1 system D-Bus object
1780 // Throw an error if there is more than 1
1781 if (subtree.size() > 1)
1782 {
1783 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1784 messages::internalError(asyncResp->res);
1785 return;
1786 }
1787 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1788 {
1789 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1790 messages::internalError(asyncResp->res);
1791 return;
1792 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001793
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001794 const std::string& path = subtree[0].first;
1795 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001796
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001797 if (service.empty())
1798 {
1799 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1800 messages::internalError(asyncResp->res);
1801 return;
1802 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001803
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001804 setDbusProperty(asyncResp, "AssetTag", service, path,
1805 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1806 "AssetTag", assetTag);
1807 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001808}
1809
1810/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001811 * @brief Validate the specified stopBootOnFault is valid and return the
1812 * stopBootOnFault name associated with that string
1813 *
1814 * @param[in] stopBootOnFaultString String representing the desired
1815 * stopBootOnFault
1816 *
1817 * @return stopBootOnFault value or empty if incoming value is not valid
1818 */
1819inline std::optional<bool>
1820 validstopBootOnFault(const std::string& stopBootOnFaultString)
1821{
1822 if (stopBootOnFaultString == "AnyFault")
1823 {
1824 return true;
1825 }
1826
1827 if (stopBootOnFaultString == "Never")
1828 {
1829 return false;
1830 }
1831
1832 return std::nullopt;
1833}
1834
1835/**
1836 * @brief Sets stopBootOnFault
1837 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001838 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001839 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1840 *
1841 * @return None.
1842 */
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001843inline void
1844 setStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1845 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001846{
Ed Tanous62598e32023-07-17 17:06:25 -07001847 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001848
1849 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1850 if (!stopBootEnabled)
1851 {
Ed Tanous62598e32023-07-17 17:06:25 -07001852 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1853 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001854 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001855 "StopBootOnFault");
1856 return;
1857 }
1858
Ginu Georgee93abac2024-06-14 17:35:27 +05301859 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1860 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001861 sdbusplus::message::object_path(
1862 "/xyz/openbmc_project/logging/settings"),
1863 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301864 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001865}
1866
1867/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001868 * @brief Sets automaticRetry (Auto Reboot)
1869 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001870 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001871 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1872 *
1873 * @return None.
1874 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001875inline void
1876 setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1877 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001878{
Ed Tanous62598e32023-07-17 17:06:25 -07001879 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001880
1881 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001882 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001883
1884 if (automaticRetryConfig == "Disabled")
1885 {
1886 autoRebootEnabled = false;
1887 }
1888 else if (automaticRetryConfig == "RetryAttempts")
1889 {
1890 autoRebootEnabled = true;
1891 }
1892 else
1893 {
Ed Tanous62598e32023-07-17 17:06:25 -07001894 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1895 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001896 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001897 "AutomaticRetryConfig");
1898 return;
1899 }
1900
Ginu Georgee93abac2024-06-14 17:35:27 +05301901 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1902 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001903 sdbusplus::message::object_path(
1904 "/xyz/openbmc_project/control/host0/auto_reboot"),
1905 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301906 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001907}
1908
Ed Tanous8d69c662023-06-21 10:29:06 -07001909inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1910{
1911 if (policy == "AlwaysOn")
1912 {
1913 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1914 }
1915 if (policy == "AlwaysOff")
1916 {
1917 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1918 }
1919 if (policy == "LastState")
1920 {
1921 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1922 }
1923 return "";
1924}
1925
Gunnar Mills69f35302020-05-17 16:06:31 -05001926/**
George Liuc6a620f2020-04-10 17:18:11 +08001927 * @brief Sets power restore policy properties.
1928 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001929 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001930 * @param[in] policy power restore policy properties from request.
1931 *
1932 * @return None.
1933 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001934inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001935 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous8d69c662023-06-21 10:29:06 -07001936 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001937{
Ed Tanous62598e32023-07-17 17:06:25 -07001938 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001939
Ed Tanous8d69c662023-06-21 10:29:06 -07001940 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001941
Ed Tanous8d69c662023-06-21 10:29:06 -07001942 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001943 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001944 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001945 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001946 return;
1947 }
1948
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001949 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301950 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001951 sdbusplus::message::object_path(
1952 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001953 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301954 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001955}
1956
AppaRao Pulia6349912019-10-18 17:16:08 +05301957/**
1958 * @brief Retrieves provisioning status
1959 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001960 * @param[in] asyncResp Shared pointer for completing asynchronous
1961 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301962 *
1963 * @return None.
1964 */
Ed Tanous25b54db2024-04-17 15:40:31 -07001965inline void
1966 getProvisioningStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301967{
Ed Tanous62598e32023-07-17 17:06:25 -07001968 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08001969 dbus::utility::getAllProperties(
1970 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1971 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001972 [asyncResp](const boost::system::error_code& ec,
1973 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001974 nlohmann::json& oemPFR =
1975 asyncResp->res
1976 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1977 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1978 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1979 oemPFR["@odata.type"] =
1980 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001981
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001982 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05301983 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001984 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1985 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07001986 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001987 FirmwareProvisioningStatus::NotProvisioned;
1988 return;
1989 }
1990
1991 const bool* provState = nullptr;
1992 const bool* lockState = nullptr;
1993
1994 const bool success = sdbusplus::unpackPropertiesNoThrow(
1995 dbus_utils::UnpackErrorPrinter(), propertiesList,
1996 "UfmProvisioned", provState, "UfmLocked", lockState);
1997
1998 if (!success)
1999 {
2000 messages::internalError(asyncResp->res);
2001 return;
2002 }
2003
2004 if ((provState == nullptr) || (lockState == nullptr))
2005 {
2006 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2007 messages::internalError(asyncResp->res);
2008 return;
2009 }
2010
2011 if (*provState)
2012 {
2013 if (*lockState)
2014 {
2015 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2016 FirmwareProvisioningStatus::ProvisionedAndLocked;
2017 }
2018 else
2019 {
2020 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2021 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2022 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302023 }
2024 else
2025 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002026 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002027 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302028 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002029 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302030}
AppaRao Pulia6349912019-10-18 17:16:08 +05302031
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302032/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002033 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002034 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002035 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002036 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002037 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002038 */
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002039inline computer_system::PowerMode
2040 translatePowerModeString(const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002041{
Chris Cainb6655102024-02-01 14:35:33 -06002042 using PowerMode = computer_system::PowerMode;
2043
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002044 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002045 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002046 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002047 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002048 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002049 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002050 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002051 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002052 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002053 if (modeString ==
2054 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002055 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002056 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002057 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002058 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002059 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2060 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002061 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002062 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002063 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002064 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2065 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002066 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002067 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002068 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002069 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2070 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002071 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002072 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002073 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002074 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002075 return PowerMode::OEM;
2076 }
2077 // Any other values would be invalid
2078 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2079 return PowerMode::Invalid;
2080}
2081
2082inline void
2083 afterGetPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2084 const boost::system::error_code& ec,
2085 const dbus::utility::DBusPropertiesMap& properties)
2086{
2087 if (ec)
2088 {
2089 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2090 messages::internalError(asyncResp->res);
2091 return;
2092 }
2093
2094 std::string powerMode;
2095 const std::vector<std::string>* allowedModes = nullptr;
2096 const bool success = sdbusplus::unpackPropertiesNoThrow(
2097 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2098 "AllowedPowerModes", allowedModes);
2099
2100 if (!success)
2101 {
2102 messages::internalError(asyncResp->res);
2103 return;
2104 }
2105
2106 nlohmann::json::array_t modeList;
2107 if (allowedModes == nullptr)
2108 {
2109 modeList.emplace_back("Static");
2110 modeList.emplace_back("MaximumPerformance");
2111 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002112 }
2113 else
2114 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002115 for (const auto& aMode : *allowedModes)
2116 {
2117 computer_system::PowerMode modeValue =
2118 translatePowerModeString(aMode);
2119 if (modeValue == computer_system::PowerMode::Invalid)
2120 {
2121 messages::internalError(asyncResp->res);
2122 continue;
2123 }
2124 modeList.emplace_back(modeValue);
2125 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002126 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002127 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002128
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002129 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2130 const computer_system::PowerMode modeValue =
2131 translatePowerModeString(powerMode);
2132 if (modeValue == computer_system::PowerMode::Invalid)
2133 {
2134 messages::internalError(asyncResp->res);
2135 return;
2136 }
2137 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2138}
Chris Cain3a2d04242021-05-28 16:57:10 -05002139/**
2140 * @brief Retrieves system power mode
2141 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002142 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002143 *
2144 * @return None.
2145 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002146inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002147{
Ed Tanous62598e32023-07-17 17:06:25 -07002148 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002149
2150 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002151 constexpr std::array<std::string_view, 1> interfaces = {
2152 "xyz.openbmc_project.Control.Power.Mode"};
2153 dbus::utility::getSubTree(
2154 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002155 [asyncResp](const boost::system::error_code& ec,
2156 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002157 if (ec)
2158 {
2159 BMCWEB_LOG_DEBUG(
2160 "DBUS response error on Power.Mode GetSubTree {}", ec);
2161 // This is an optional D-Bus object so just return if
2162 // error occurs
2163 return;
2164 }
2165 if (subtree.empty())
2166 {
2167 // As noted above, this is an optional interface so just return
2168 // if there is no instance found
2169 return;
2170 }
2171 if (subtree.size() > 1)
2172 {
2173 // More then one PowerMode object is not supported and is an
2174 // error
2175 BMCWEB_LOG_DEBUG(
2176 "Found more than 1 system D-Bus Power.Mode objects: {}",
2177 subtree.size());
2178 messages::internalError(asyncResp->res);
2179 return;
2180 }
2181 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2182 {
2183 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2184 messages::internalError(asyncResp->res);
2185 return;
2186 }
2187 const std::string& path = subtree[0].first;
2188 const std::string& service = subtree[0].second.begin()->first;
2189 if (service.empty())
2190 {
2191 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2192 messages::internalError(asyncResp->res);
2193 return;
2194 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002195
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002196 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002197 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002198 *crow::connections::systemBus, service, path,
2199 "xyz.openbmc_project.Control.Power.Mode",
2200 [asyncResp](
2201 const boost::system::error_code& ec2,
2202 const dbus::utility::DBusPropertiesMap& properties) {
2203 afterGetPowerMode(asyncResp, ec2, properties);
2204 });
George Liue99073f2022-12-09 11:06:16 +08002205 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002206}
2207
2208/**
2209 * @brief Validate the specified mode is valid and return the PowerMode
2210 * name associated with that string
2211 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002212 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002213 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002214 *
2215 * @return PowerMode value or empty string if mode is not valid
2216 */
2217inline std::string
Ed Tanousac106bf2023-06-07 09:24:59 -07002218 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cainb6655102024-02-01 14:35:33 -06002219 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002220{
Chris Cainb6655102024-02-01 14:35:33 -06002221 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002222 std::string mode;
2223
Chris Cainb6655102024-02-01 14:35:33 -06002224 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002225 {
2226 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2227 }
Chris Cainb6655102024-02-01 14:35:33 -06002228 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002229 {
George Liu0fda0f12021-11-16 10:06:17 +08002230 mode =
2231 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002232 }
Chris Cainb6655102024-02-01 14:35:33 -06002233 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002234 {
2235 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2236 }
Chris Cainb6655102024-02-01 14:35:33 -06002237 else if (modeValue == PowerMode::BalancedPerformance)
2238 {
2239 mode =
2240 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2241 }
2242 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2243 {
2244 mode =
2245 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2246 }
2247 else if (modeValue == PowerMode::EfficiencyFavorPower)
2248 {
2249 mode =
2250 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2251 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002252 else
2253 {
Chris Cainb6655102024-02-01 14:35:33 -06002254 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002255 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002256 }
2257 return mode;
2258}
2259
2260/**
2261 * @brief Sets system power mode.
2262 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002263 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002264 * @param[in] pmode System power mode from request.
2265 *
2266 * @return None.
2267 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002268inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002269 const std::string& pmode)
2270{
Ed Tanous62598e32023-07-17 17:06:25 -07002271 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002272
Ed Tanousac106bf2023-06-07 09:24:59 -07002273 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002274 if (powerMode.empty())
2275 {
2276 return;
2277 }
2278
2279 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002280 constexpr std::array<std::string_view, 1> interfaces = {
2281 "xyz.openbmc_project.Control.Power.Mode"};
2282 dbus::utility::getSubTree(
2283 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002284 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002285 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002286 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002287 if (ec)
2288 {
2289 BMCWEB_LOG_ERROR(
2290 "DBUS response error on Power.Mode GetSubTree {}", ec);
2291 // This is an optional D-Bus object, but user attempted to patch
2292 messages::internalError(asyncResp->res);
2293 return;
2294 }
2295 if (subtree.empty())
2296 {
2297 // This is an optional D-Bus object, but user attempted to patch
2298 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2299 "PowerMode");
2300 return;
2301 }
2302 if (subtree.size() > 1)
2303 {
2304 // More then one PowerMode object is not supported and is an
2305 // error
2306 BMCWEB_LOG_DEBUG(
2307 "Found more than 1 system D-Bus Power.Mode objects: {}",
2308 subtree.size());
2309 messages::internalError(asyncResp->res);
2310 return;
2311 }
2312 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2313 {
2314 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2315 messages::internalError(asyncResp->res);
2316 return;
2317 }
2318 const std::string& path = subtree[0].first;
2319 const std::string& service = subtree[0].second.begin()->first;
2320 if (service.empty())
2321 {
2322 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2323 messages::internalError(asyncResp->res);
2324 return;
2325 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002326
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002327 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002328
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002329 // Set the Power Mode property
2330 setDbusProperty(asyncResp, "PowerMode", service, path,
2331 "xyz.openbmc_project.Control.Power.Mode",
2332 "PowerMode", powerMode);
2333 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002334}
2335
2336/**
Yong Li51709ff2019-09-30 14:13:04 +08002337 * @brief Translates watchdog timeout action DBUS property value to redfish.
2338 *
2339 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2340 *
2341 * @return Returns as a string, the timeout action in Redfish terms. If
2342 * translation cannot be done, returns an empty string.
2343 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002344inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002345{
2346 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2347 {
2348 return "None";
2349 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002350 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002351 {
2352 return "ResetSystem";
2353 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002354 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002355 {
2356 return "PowerDown";
2357 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002358 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002359 {
2360 return "PowerCycle";
2361 }
2362
2363 return "";
2364}
2365
2366/**
Yong Lic45f0082019-10-10 14:19:01 +08002367 *@brief Translates timeout action from Redfish to DBUS property value.
2368 *
2369 *@param[in] rfAction The timeout action in Redfish.
2370 *
2371 *@return Returns as a string, the time_out action as expected by DBUS.
2372 *If translation cannot be done, returns an empty string.
2373 */
2374
Ed Tanous23a21a12020-07-25 04:45:05 +00002375inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002376{
2377 if (rfAction == "None")
2378 {
2379 return "xyz.openbmc_project.State.Watchdog.Action.None";
2380 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002381 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002382 {
2383 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2384 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002385 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002386 {
2387 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2388 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002389 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002390 {
2391 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2392 }
2393
2394 return "";
2395}
2396
2397/**
Yong Li51709ff2019-09-30 14:13:04 +08002398 * @brief Retrieves host watchdog timer properties over DBUS
2399 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002400 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002401 *
2402 * @return None.
2403 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002404inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002405 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002406{
Ed Tanous62598e32023-07-17 17:06:25 -07002407 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002408 dbus::utility::getAllProperties(
2409 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002410 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002411 [asyncResp](const boost::system::error_code& ec,
2412 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002413 if (ec)
2414 {
2415 // watchdog service is stopped
2416 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2417 return;
2418 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002419
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002420 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002421
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002422 nlohmann::json& hostWatchdogTimer =
2423 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002424
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002425 // watchdog service is running/enabled
2426 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002427
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002428 const bool* enabled = nullptr;
2429 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002430
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002431 const bool success = sdbusplus::unpackPropertiesNoThrow(
2432 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2433 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002434
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002435 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002436 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002437 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002438 return;
2439 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002440
2441 if (enabled != nullptr)
2442 {
2443 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2444 }
2445
2446 if (expireAction != nullptr)
2447 {
2448 std::string action = dbusToRfWatchdogAction(*expireAction);
2449 if (action.empty())
2450 {
2451 messages::internalError(asyncResp->res);
2452 return;
2453 }
2454 hostWatchdogTimer["TimeoutAction"] = action;
2455 }
2456 });
Yong Li51709ff2019-09-30 14:13:04 +08002457}
2458
2459/**
Yong Lic45f0082019-10-10 14:19:01 +08002460 * @brief Sets Host WatchDog Timer properties.
2461 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002462 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002463 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2464 * RF request.
2465 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2466 *
2467 * @return None.
2468 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002469inline void
2470 setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2471 const std::optional<bool> wdtEnable,
2472 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002473{
Ed Tanous62598e32023-07-17 17:06:25 -07002474 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002475
2476 if (wdtTimeOutAction)
2477 {
2478 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2479 // check if TimeOut Action is Valid
2480 if (wdtTimeOutActStr.empty())
2481 {
Ed Tanous62598e32023-07-17 17:06:25 -07002482 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2483 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002484 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002485 "TimeoutAction");
2486 return;
2487 }
2488
Ginu Georgee93abac2024-06-14 17:35:27 +05302489 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2490 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002491 sdbusplus::message::object_path(
2492 "/xyz/openbmc_project/watchdog/host0"),
2493 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302494 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002495 }
2496
2497 if (wdtEnable)
2498 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302499 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2500 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002501 sdbusplus::message::object_path(
2502 "/xyz/openbmc_project/watchdog/host0"),
2503 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302504 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002505 }
2506}
2507
Chris Cain37bbf982021-09-20 10:53:09 -05002508/**
2509 * @brief Parse the Idle Power Saver properties into json
2510 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002511 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002512 * @param[in] properties IPS property data from DBus.
2513 *
2514 * @return true if successful
2515 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002516inline bool
Ed Tanousac106bf2023-06-07 09:24:59 -07002517 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002518 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002519{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002520 const bool* enabled = nullptr;
2521 const uint8_t* enterUtilizationPercent = nullptr;
2522 const uint64_t* enterDwellTime = nullptr;
2523 const uint8_t* exitUtilizationPercent = nullptr;
2524 const uint64_t* exitDwellTime = nullptr;
2525
2526 const bool success = sdbusplus::unpackPropertiesNoThrow(
2527 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002528 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2529 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2530 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002531
2532 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002533 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002534 return false;
2535 }
2536
2537 if (enabled != nullptr)
2538 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002539 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002540 }
2541
2542 if (enterUtilizationPercent != nullptr)
2543 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002544 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002545 *enterUtilizationPercent;
2546 }
2547
2548 if (enterDwellTime != nullptr)
2549 {
2550 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002551 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002552 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2553 .count();
2554 }
2555
2556 if (exitUtilizationPercent != nullptr)
2557 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002558 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002559 *exitUtilizationPercent;
2560 }
2561
2562 if (exitDwellTime != nullptr)
2563 {
2564 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002565 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002566 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2567 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002568 }
2569
2570 return true;
2571}
2572
2573/**
2574 * @brief Retrieves host watchdog timer properties over DBUS
2575 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002576 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002577 *
2578 * @return None.
2579 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002580inline void
2581 getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002582{
Ed Tanous62598e32023-07-17 17:06:25 -07002583 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002584
2585 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002586 constexpr std::array<std::string_view, 1> interfaces = {
2587 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2588 dbus::utility::getSubTree(
2589 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002590 [asyncResp](const boost::system::error_code& ec,
2591 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002592 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002593 {
Ed Tanous62598e32023-07-17 17:06:25 -07002594 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002595 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2596 ec);
2597 messages::internalError(asyncResp->res);
2598 return;
2599 }
2600 if (subtree.empty())
2601 {
2602 // This is an optional interface so just return
2603 // if there is no instance found
2604 BMCWEB_LOG_DEBUG("No instances found");
2605 return;
2606 }
2607 if (subtree.size() > 1)
2608 {
2609 // More then one PowerIdlePowerSaver object is not supported and
2610 // is an error
2611 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2612 "Power.IdlePowerSaver objects: {}",
2613 subtree.size());
2614 messages::internalError(asyncResp->res);
2615 return;
2616 }
2617 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2618 {
2619 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2620 messages::internalError(asyncResp->res);
2621 return;
2622 }
2623 const std::string& path = subtree[0].first;
2624 const std::string& service = subtree[0].second.begin()->first;
2625 if (service.empty())
2626 {
2627 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002628 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002629 return;
2630 }
2631
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002632 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002633 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002634 *crow::connections::systemBus, service, path,
2635 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2636 [asyncResp](
2637 const boost::system::error_code& ec2,
2638 const dbus::utility::DBusPropertiesMap& properties) {
2639 if (ec2)
2640 {
2641 BMCWEB_LOG_ERROR(
2642 "DBUS response error on IdlePowerSaver GetAll: {}",
2643 ec2);
2644 messages::internalError(asyncResp->res);
2645 return;
2646 }
2647
2648 if (!parseIpsProperties(asyncResp, properties))
2649 {
2650 messages::internalError(asyncResp->res);
2651 return;
2652 }
2653 });
George Liue99073f2022-12-09 11:06:16 +08002654 });
Chris Cain37bbf982021-09-20 10:53:09 -05002655
Ed Tanous62598e32023-07-17 17:06:25 -07002656 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002657}
2658
2659/**
2660 * @brief Sets Idle Power Saver properties.
2661 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002662 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002663 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2664 * RF request.
2665 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2666 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2667 * before entering idle state.
2668 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2669 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2670 * before exiting idle state
2671 *
2672 * @return None.
2673 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002674inline void setIdlePowerSaver(
2675 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2676 const std::optional<bool> ipsEnable,
2677 const std::optional<uint8_t> ipsEnterUtil,
2678 const std::optional<uint64_t> ipsEnterTime,
2679 const std::optional<uint8_t> ipsExitUtil,
2680 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002681{
Ed Tanous62598e32023-07-17 17:06:25 -07002682 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002683
2684 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002685 constexpr std::array<std::string_view, 1> interfaces = {
2686 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2687 dbus::utility::getSubTree(
2688 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002689 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002690 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002691 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002692 if (ec)
2693 {
2694 BMCWEB_LOG_ERROR(
2695 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2696 ec);
2697 messages::internalError(asyncResp->res);
2698 return;
2699 }
2700 if (subtree.empty())
2701 {
2702 // This is an optional D-Bus object, but user attempted to patch
2703 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2704 "IdlePowerSaver");
2705 return;
2706 }
2707 if (subtree.size() > 1)
2708 {
2709 // More then one PowerIdlePowerSaver object is not supported and
2710 // is an error
2711 BMCWEB_LOG_DEBUG(
2712 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2713 subtree.size());
2714 messages::internalError(asyncResp->res);
2715 return;
2716 }
2717 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2718 {
2719 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2720 messages::internalError(asyncResp->res);
2721 return;
2722 }
2723 const std::string& path = subtree[0].first;
2724 const std::string& service = subtree[0].second.begin()->first;
2725 if (service.empty())
2726 {
2727 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2728 messages::internalError(asyncResp->res);
2729 return;
2730 }
Chris Cain37bbf982021-09-20 10:53:09 -05002731
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002732 // Valid Power IdlePowerSaver object found, now set any values that
2733 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002734
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002735 if (ipsEnable)
2736 {
2737 setDbusProperty(
2738 asyncResp, "IdlePowerSaver/Enabled", service, path,
2739 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2740 "Enabled", *ipsEnable);
2741 }
2742 if (ipsEnterUtil)
2743 {
2744 setDbusProperty(
2745 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2746 service, path,
2747 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2748 "EnterUtilizationPercent", *ipsEnterUtil);
2749 }
2750 if (ipsEnterTime)
2751 {
2752 // Convert from seconds into milliseconds for DBus
2753 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2754 setDbusProperty(
2755 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2756 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2757 "EnterDwellTime", timeMilliseconds);
2758 }
2759 if (ipsExitUtil)
2760 {
2761 setDbusProperty(
2762 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2763 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2764 "ExitUtilizationPercent", *ipsExitUtil);
2765 }
2766 if (ipsExitTime)
2767 {
2768 // Convert from seconds into milliseconds for DBus
2769 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2770 setDbusProperty(
2771 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2772 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2773 "ExitDwellTime", timeMilliseconds);
2774 }
2775 });
Chris Cain37bbf982021-09-20 10:53:09 -05002776
Ed Tanous62598e32023-07-17 17:06:25 -07002777 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002778}
2779
Ed Tanousc1e219d2023-06-07 10:34:33 -07002780inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002781 crow::App& app, const crow::Request& req,
2782 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2783{
2784 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2785 {
2786 return;
2787 }
2788 asyncResp->res.addHeader(
2789 boost::beast::http::field::link,
2790 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2791}
2792
Ed Tanousc1e219d2023-06-07 10:34:33 -07002793inline void handleComputerSystemCollectionGet(
2794 crow::App& app, const crow::Request& req,
2795 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2796{
2797 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2798 {
2799 return;
2800 }
2801
2802 asyncResp->res.addHeader(
2803 boost::beast::http::field::link,
2804 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2805 asyncResp->res.jsonValue["@odata.type"] =
2806 "#ComputerSystemCollection.ComputerSystemCollection";
2807 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2808 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2809
2810 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2811 ifaceArray = nlohmann::json::array();
Ed Tanous25b54db2024-04-17 15:40:31 -07002812 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002813 {
2814 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2815 // Option currently returns no systems. TBD
2816 return;
2817 }
2818 asyncResp->res.jsonValue["Members@odata.count"] = 1;
2819 nlohmann::json::object_t system;
Ed Tanous253f11b2024-05-16 09:38:31 -07002820 system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
2821 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002822 ifaceArray.emplace_back(std::move(system));
Gunnar Mills68896202024-08-21 11:34:20 -05002823
2824 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2825 {
2826 BMCWEB_LOG_DEBUG("Hypervisor is available");
2827 asyncResp->res.jsonValue["Members@odata.count"] = 2;
2828
2829 nlohmann::json::object_t hypervisor;
2830 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2831 ifaceArray.emplace_back(std::move(hypervisor));
2832 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07002833}
2834
Yong Lic45f0082019-10-10 14:19:01 +08002835/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002836 * Function transceives data with dbus directly.
2837 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002838inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839{
Patrick Williams89492a12023-05-10 07:51:34 -05002840 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2841 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2842 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002844 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002845
2846 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002847 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002848 if (ec)
2849 {
2850 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2851 messages::internalError(asyncResp->res);
2852 return;
2853 }
2854 messages::success(asyncResp->res);
2855 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002856 serviceName, objectPath, interfaceName, method);
2857}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002858
Ed Tanousc1e219d2023-06-07 10:34:33 -07002859inline void handleComputerSystemResetActionPost(
2860 crow::App& app, const crow::Request& req,
2861 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2862 const std::string& systemName)
2863{
2864 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2865 {
2866 return;
2867 }
Gunnar Millsdd7090e2024-07-30 15:23:05 -05002868
2869 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2870 {
2871 if (systemName == "hypervisor")
2872 {
2873 handleHypervisorSystemResetPost(req, asyncResp);
2874 return;
2875 }
2876 }
2877
Ed Tanous253f11b2024-05-16 09:38:31 -07002878 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002879 {
2880 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2881 systemName);
2882 return;
2883 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002884 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002885 {
2886 // Option currently returns no systems. TBD
2887 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2888 systemName);
2889 return;
2890 }
2891 std::string resetType;
2892 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2893 {
2894 return;
2895 }
2896
2897 // Get the command and host vs. chassis
2898 std::string command;
2899 bool hostCommand = true;
2900 if ((resetType == "On") || (resetType == "ForceOn"))
2901 {
2902 command = "xyz.openbmc_project.State.Host.Transition.On";
2903 hostCommand = true;
2904 }
2905 else if (resetType == "ForceOff")
2906 {
2907 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2908 hostCommand = false;
2909 }
2910 else if (resetType == "ForceRestart")
2911 {
2912 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2913 hostCommand = true;
2914 }
2915 else if (resetType == "GracefulShutdown")
2916 {
2917 command = "xyz.openbmc_project.State.Host.Transition.Off";
2918 hostCommand = true;
2919 }
2920 else if (resetType == "GracefulRestart")
2921 {
2922 command =
2923 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2924 hostCommand = true;
2925 }
2926 else if (resetType == "PowerCycle")
2927 {
2928 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2929 hostCommand = true;
2930 }
2931 else if (resetType == "Nmi")
2932 {
2933 doNMI(asyncResp);
2934 return;
2935 }
2936 else
2937 {
2938 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2939 return;
2940 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002941 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002942
2943 if (hostCommand)
2944 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302945 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002946 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302947 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002948 }
2949 else
2950 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302951 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08002952 statePath / "chassis0",
2953 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302954 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002955 }
2956}
2957
Ed Tanousc1e219d2023-06-07 10:34:33 -07002958inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002959 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002960 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2961 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002962{
2963 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2964 {
2965 return;
2966 }
2967
2968 asyncResp->res.addHeader(
2969 boost::beast::http::field::link,
2970 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2971}
2972
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002973inline void afterPortRequest(
2974 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2975 const boost::system::error_code& ec,
2976 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2977{
2978 if (ec)
2979 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002980 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002981 messages::internalError(asyncResp->res);
2982 return;
2983 }
2984 for (const auto& data : socketData)
2985 {
2986 const std::string& socketPath = get<0>(data);
2987 const std::string& protocolName = get<1>(data);
2988 bool isProtocolEnabled = get<2>(data);
2989 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2990 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2991 // need to retrieve port number for
2992 // obmc-console-ssh service
2993 if (protocolName == "SSH")
2994 {
2995 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002996 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002997 int portNumber) {
2998 if (ec1)
2999 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003000 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003001 messages::internalError(asyncResp->res);
3002 return;
3003 }
3004 nlohmann::json& dataJson1 =
3005 asyncResp->res.jsonValue["SerialConsole"];
3006 dataJson1[protocolName]["Port"] = portNumber;
3007 });
3008 }
3009 }
3010}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003011
3012inline void
3013 handleComputerSystemGet(crow::App& app, const crow::Request& req,
3014 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3015 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003016{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003017 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3018 {
3019 return;
3020 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003021
Ed Tanous25b54db2024-04-17 15:40:31 -07003022 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003023 {
3024 // Option currently returns no systems. TBD
3025 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3026 systemName);
3027 return;
3028 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003029
Gunnar Mills68896202024-08-21 11:34:20 -05003030 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003031 {
Gunnar Mills68896202024-08-21 11:34:20 -05003032 if (systemName == "hypervisor")
3033 {
3034 handleHypervisorSystemGet(asyncResp);
3035 return;
3036 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003037 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003038
Ed Tanous253f11b2024-05-16 09:38:31 -07003039 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003040 {
3041 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3042 systemName);
3043 return;
3044 }
3045 asyncResp->res.addHeader(
3046 boost::beast::http::field::link,
3047 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3048 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003049 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003050 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3051 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanous539d8c62024-06-19 14:38:27 -07003052 asyncResp->res.jsonValue["SystemType"] =
3053 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003054 asyncResp->res.jsonValue["Description"] = "Computer System";
3055 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003056 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003057 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003058 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3059 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003060
Ed Tanous253f11b2024-05-16 09:38:31 -07003061 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3062 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3063 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3064 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3065 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3066 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003067 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003068 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3069 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003070
Ed Tanousc1e219d2023-06-07 10:34:33 -07003071 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003072 boost::urls::format(
3073 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3074 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003075 asyncResp->res
3076 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003077 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3078 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003079
Ed Tanous253f11b2024-05-16 09:38:31 -07003080 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3081 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3082 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3083 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003084
Ed Tanousc1e219d2023-06-07 10:34:33 -07003085 nlohmann::json::array_t managedBy;
3086 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003087 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3088 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003089 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003090 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3091 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003092
Ed Tanousc1e219d2023-06-07 10:34:33 -07003093 // Fill in SerialConsole info
3094 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3095 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003096
Ed Tanousc1e219d2023-06-07 10:34:33 -07003097 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3098 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3099 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3100 "Press ~. to exit console";
3101 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3102 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003103
Ed Tanous25b54db2024-04-17 15:40:31 -07003104 if constexpr (BMCWEB_KVM)
3105 {
3106 // Fill in GraphicalConsole info
3107 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3108 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3109 4;
3110 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3111 nlohmann::json::array_t({"KVMIP"});
3112 }
James Feistb49ac872019-05-21 15:12:01 -07003113
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003114 getMainChassisId(
3115 asyncResp, [](const std::string& chassisId,
3116 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3117 nlohmann::json::array_t chassisArray;
3118 nlohmann::json& chassis = chassisArray.emplace_back();
3119 chassis["@odata.id"] =
3120 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3121 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3122 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003123
George Liu59a17e42022-10-08 09:27:47 +08003124 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003125 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3126 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003127 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003128 getHostState(asyncResp);
3129 getBootProperties(asyncResp);
3130 getBootProgress(asyncResp);
3131 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003132 pcie_util::getPCIeDeviceList(asyncResp,
3133 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003134 getHostWatchdogTimer(asyncResp);
3135 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003136 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003137 getAutomaticRetryPolicy(asyncResp);
3138 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003139 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3140 {
3141 getProvisioningStatus(asyncResp);
3142 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003143 getTrustedModuleRequiredToBoot(asyncResp);
3144 getPowerMode(asyncResp);
3145 getIdlePowerSaver(asyncResp);
3146}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003147
Ed Tanousc1e219d2023-06-07 10:34:33 -07003148inline void handleComputerSystemPatch(
3149 crow::App& app, const crow::Request& req,
3150 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3151 const std::string& systemName)
3152{
3153 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3154 {
3155 return;
3156 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003157 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003158 {
3159 // Option currently returns no systems. TBD
3160 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3161 systemName);
3162 return;
3163 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003164 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003165 {
3166 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3167 systemName);
3168 return;
3169 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003170
Ed Tanousc1e219d2023-06-07 10:34:33 -07003171 asyncResp->res.addHeader(
3172 boost::beast::http::field::link,
3173 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003174
Ed Tanousc1e219d2023-06-07 10:34:33 -07003175 std::optional<bool> locationIndicatorActive;
3176 std::optional<std::string> indicatorLed;
3177 std::optional<std::string> assetTag;
3178 std::optional<std::string> powerRestorePolicy;
3179 std::optional<std::string> powerMode;
3180 std::optional<bool> wdtEnable;
3181 std::optional<std::string> wdtTimeOutAction;
3182 std::optional<std::string> bootSource;
3183 std::optional<std::string> bootType;
3184 std::optional<std::string> bootEnable;
3185 std::optional<std::string> bootAutomaticRetry;
3186 std::optional<uint32_t> bootAutomaticRetryAttempts;
3187 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003188 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003189 std::optional<bool> ipsEnable;
3190 std::optional<uint8_t> ipsEnterUtil;
3191 std::optional<uint64_t> ipsEnterTime;
3192 std::optional<uint8_t> ipsExitUtil;
3193 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003194
Myung Baeafc474a2024-10-09 00:53:29 -07003195 if (!json_util::readJsonPatch( //
3196 req, asyncResp->res, //
3197 "AssetTag", assetTag, //
3198 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts, //
3199 "Boot/AutomaticRetryConfig", bootAutomaticRetry, //
3200 "Boot/BootSourceOverrideEnabled", bootEnable, //
3201 "Boot/BootSourceOverrideMode", bootType, //
3202 "Boot/BootSourceOverrideTarget", bootSource, //
3203 "Boot/StopBootOnFault", stopBootOnFault, //
3204 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired, //
3205 "HostWatchdogTimer/FunctionEnabled", wdtEnable, //
3206 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction, //
3207 "IdlePowerSaver/Enabled", ipsEnable, //
3208 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime, //
3209 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil, //
3210 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime, //
3211 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil, //
3212 "IndicatorLED", indicatorLed, //
3213 "LocationIndicatorActive", locationIndicatorActive, //
3214 "PowerMode", powerMode, //
3215 "PowerRestorePolicy", powerRestorePolicy //
3216 ))
Ed Tanousab344222024-08-07 18:01:23 -07003217 {
3218 return;
3219 }
James Feistb49ac872019-05-21 15:12:01 -07003220
Ed Tanousc1e219d2023-06-07 10:34:33 -07003221 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003222
Ed Tanousc1e219d2023-06-07 10:34:33 -07003223 if (assetTag)
3224 {
3225 setAssetTag(asyncResp, *assetTag);
3226 }
James Feistb49ac872019-05-21 15:12:01 -07003227
Ed Tanousc1e219d2023-06-07 10:34:33 -07003228 if (wdtEnable || wdtTimeOutAction)
3229 {
3230 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3231 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003232
Ed Tanousc1e219d2023-06-07 10:34:33 -07003233 if (bootSource || bootType || bootEnable)
3234 {
3235 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3236 }
3237 if (bootAutomaticRetry)
3238 {
3239 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3240 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003241
Ed Tanousc1e219d2023-06-07 10:34:33 -07003242 if (bootAutomaticRetryAttempts)
3243 {
3244 setAutomaticRetryAttempts(asyncResp,
3245 bootAutomaticRetryAttempts.value());
3246 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003247
Ed Tanousc1e219d2023-06-07 10:34:33 -07003248 if (bootTrustedModuleRequired)
3249 {
3250 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3251 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003252
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003253 if (stopBootOnFault)
3254 {
3255 setStopBootOnFault(asyncResp, *stopBootOnFault);
3256 }
3257
Ed Tanousc1e219d2023-06-07 10:34:33 -07003258 if (locationIndicatorActive)
3259 {
George Liu59a17e42022-10-08 09:27:47 +08003260 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003261 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003262
Ed Tanousc1e219d2023-06-07 10:34:33 -07003263 // TODO (Gunnar): Remove IndicatorLED after enough time has
3264 // passed
3265 if (indicatorLed)
3266 {
3267 setIndicatorLedState(asyncResp, *indicatorLed);
3268 asyncResp->res.addHeader(boost::beast::http::field::warning,
3269 "299 - \"IndicatorLED is deprecated. Use "
3270 "LocationIndicatorActive instead.\"");
3271 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003272
Ed Tanousc1e219d2023-06-07 10:34:33 -07003273 if (powerRestorePolicy)
3274 {
3275 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3276 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003277
Ed Tanousc1e219d2023-06-07 10:34:33 -07003278 if (powerMode)
3279 {
3280 setPowerMode(asyncResp, *powerMode);
3281 }
Chris Cain37bbf982021-09-20 10:53:09 -05003282
Ed Tanousc1e219d2023-06-07 10:34:33 -07003283 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3284 {
3285 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3286 ipsExitUtil, ipsExitTime);
3287 }
3288}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303289
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003290inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003291 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003292 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003293 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003294{
3295 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3296 {
3297 return;
3298 }
3299 asyncResp->res.addHeader(
3300 boost::beast::http::field::link,
3301 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3302}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003303
3304/**
3305 * @brief Translates allowed host transitions to redfish string
3306 *
3307 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3308 * @param[out] allowableValues The translated host transition(s)
3309 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303310 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003311 * allowableValues. If translation not possible, does nothing to
3312 * allowableValues.
3313 */
3314inline void
3315 dbusToRfAllowedHostTransitions(const std::string& dbusAllowedHostTran,
3316 nlohmann::json::array_t& allowableValues)
3317{
3318 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3319 {
3320 allowableValues.emplace_back(resource::ResetType::On);
3321 allowableValues.emplace_back(resource::ResetType::ForceOn);
3322 }
3323 else if (dbusAllowedHostTran ==
3324 "xyz.openbmc_project.State.Host.Transition.Off")
3325 {
3326 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3327 }
3328 else if (dbusAllowedHostTran ==
3329 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3330 {
3331 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3332 }
3333 else if (dbusAllowedHostTran ==
3334 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3335 {
3336 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3337 }
3338 else
3339 {
3340 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3341 }
3342}
3343
3344inline void afterGetAllowedHostTransitions(
3345 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3346 const boost::system::error_code& ec,
3347 const std::vector<std::string>& allowedHostTransitions)
3348{
3349 nlohmann::json::array_t allowableValues;
3350
3351 // Supported on all systems currently
3352 allowableValues.emplace_back(resource::ResetType::ForceOff);
3353 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3354 allowableValues.emplace_back(resource::ResetType::Nmi);
3355
3356 if (ec)
3357 {
Ed Tanouse715d142024-03-07 15:47:37 -08003358 if ((ec.value() ==
3359 boost::system::linux_error::bad_request_descriptor) ||
3360 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003361 {
3362 // Property not implemented so just return defaults
3363 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3364 allowableValues.emplace_back(resource::ResetType::On);
3365 allowableValues.emplace_back(resource::ResetType::ForceOn);
3366 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3367 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3368 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3369 }
3370 else
3371 {
3372 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3373 messages::internalError(asyncResp->res);
3374 return;
3375 }
3376 }
3377 else
3378 {
3379 for (const std::string& transition : allowedHostTransitions)
3380 {
3381 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3382 dbusToRfAllowedHostTransitions(transition, allowableValues);
3383 }
3384 }
3385
3386 nlohmann::json::object_t parameter;
3387 parameter["Name"] = "ResetType";
3388 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003389 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003390 parameter["AllowableValues"] = std::move(allowableValues);
3391 nlohmann::json::array_t parameters;
3392 parameters.emplace_back(std::move(parameter));
3393 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3394}
3395
Ed Tanousc1e219d2023-06-07 10:34:33 -07003396inline void handleSystemCollectionResetActionGet(
3397 crow::App& app, const crow::Request& req,
3398 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3399 const std::string& systemName)
3400{
3401 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3402 {
3403 return;
3404 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003405 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003406 {
3407 // Option currently returns no systems. TBD
3408 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3409 systemName);
3410 return;
3411 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003412
Gunnar Mills68896202024-08-21 11:34:20 -05003413 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003414 {
Gunnar Mills68896202024-08-21 11:34:20 -05003415 if (systemName == "hypervisor")
3416 {
3417 handleHypervisorResetActionGet(asyncResp);
3418 return;
3419 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003420 }
3421
Ed Tanous253f11b2024-05-16 09:38:31 -07003422 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003423 {
3424 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3425 systemName);
3426 return;
3427 }
3428
3429 asyncResp->res.addHeader(
3430 boost::beast::http::field::link,
3431 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3432
3433 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003434 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3435 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003436 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3437 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3438 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3439
Andrew Geissler33e1f122024-02-26 21:10:16 -06003440 // Look to see if system defines AllowedHostTransitions
Ed Tanousdeae6a72024-11-11 21:58:57 -08003441 dbus::utility::getProperty<std::vector<std::string>>(
3442 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
3443 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
Andrew Geissler33e1f122024-02-26 21:10:16 -06003444 [asyncResp](const boost::system::error_code& ec,
3445 const std::vector<std::string>& allowedHostTransitions) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003446 afterGetAllowedHostTransitions(asyncResp, ec,
3447 allowedHostTransitions);
3448 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003449}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303450/**
3451 * SystemResetActionInfo derived class for delivering Computer Systems
3452 * ResetType AllowableValues using ResetInfo schema.
3453 */
Ed Tanous100afe52023-06-07 13:30:46 -07003454inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303455{
Ed Tanous100afe52023-06-07 13:30:46 -07003456 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3457 .privileges(redfish::privileges::headComputerSystemCollection)
3458 .methods(boost::beast::http::verb::head)(
3459 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3460
3461 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3462 .privileges(redfish::privileges::getComputerSystemCollection)
3463 .methods(boost::beast::http::verb::get)(
3464 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3465
3466 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3467 .privileges(redfish::privileges::headComputerSystem)
3468 .methods(boost::beast::http::verb::head)(
3469 std::bind_front(handleComputerSystemHead, std::ref(app)));
3470
3471 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3472 .privileges(redfish::privileges::getComputerSystem)
3473 .methods(boost::beast::http::verb::get)(
3474 std::bind_front(handleComputerSystemGet, std::ref(app)));
3475
3476 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3477 .privileges(redfish::privileges::patchComputerSystem)
3478 .methods(boost::beast::http::verb::patch)(
3479 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3480
3481 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3482 .privileges(redfish::privileges::postComputerSystem)
3483 .methods(boost::beast::http::verb::post)(std::bind_front(
3484 handleComputerSystemResetActionPost, std::ref(app)));
3485
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003486 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003487 .privileges(redfish::privileges::headActionInfo)
3488 .methods(boost::beast::http::verb::head)(std::bind_front(
3489 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003490 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003491 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003492 .methods(boost::beast::http::verb::get)(std::bind_front(
3493 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003494}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003495} // namespace redfish