blob: a8751b00a6918aa41a6b6f48639eed293eda3129 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070021#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
Ed Tanous8d69c662023-06-21 10:29:06 -070023#include "generated/enums/computer_system.hpp"
Andrew Geissler33e1f122024-02-26 21:10:16 -060024#include "generated/enums/resource.hpp"
James Feistb49ac872019-05-21 15:12:01 -070025#include "health.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060026#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080027#include "led.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070028#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080029#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080030#include "registries/privilege_registry.hpp"
31#include "utils/dbus_utils.hpp"
32#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050033#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080034#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070035#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080036
Andrew Geisslerfc903b32023-05-31 14:15:42 -040037#include <boost/asio/error.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070038#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080039#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060040#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070041#include <boost/url/format.hpp>
Chris Cainb6655102024-02-01 14:35:33 -060042#include <generated/enums/computer_system.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070043#include <sdbusplus/asio/property.hpp>
Andrew Geisslerfc903b32023-05-31 14:15:42 -040044#include <sdbusplus/message.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020045#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050046
George Liu7a1dbc42022-12-07 16:03:22 +080047#include <array>
Andrew Geissler33e1f122024-02-26 21:10:16 -060048#include <memory>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060049#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080050#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080051#include <variant>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060052#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020053
Ed Tanous1abe55e2018-09-05 08:30:59 -070054namespace redfish
55{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020056
Abhishek Patel5c3e9272021-06-24 10:11:33 -050057const static std::array<std::pair<std::string_view, std::string_view>, 2>
58 protocolToDBusForSystems{
59 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
60
Alpana Kumari9d3ae102019-04-12 06:49:32 -050061/**
62 * @brief Updates the Functional State of DIMMs
63 *
Ed Tanousac106bf2023-06-07 09:24:59 -070064 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065 * @param[in] dimmState Dimm's Functional state, true/false
66 *
67 * @return None.
68 */
zhanghch058d1b46d2021-04-01 11:18:24 +080069inline void
Ed Tanousac106bf2023-06-07 09:24:59 -070070 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070071 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050072{
Ed Tanous62598e32023-07-17 17:06:25 -070073 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050074
Gunnar Mills4e0453b2020-07-08 14:00:30 -050075 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050076 // Update STATE only if previous State was DISABLED and current Dimm is
77 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070078 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070079 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050080 if (prevMemSummary == "Disabled")
81 {
Ed Tanouse05aec52022-01-25 10:28:56 -080082 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050083 {
Ed Tanousac106bf2023-06-07 09:24:59 -070084 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050085 "Enabled";
86 }
87 }
88}
89
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050090/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091 * @brief Update "ProcessorSummary" "Status" "State" based on
92 * CPU Functional State
93 *
Ed Tanousac106bf2023-06-07 09:24:59 -070094 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050095 * @param[in] cpuFunctionalState is CPU functional true/false
96 *
97 * @return None.
98 */
Ed Tanousac106bf2023-06-07 09:24:59 -070099inline void modifyCpuFunctionalState(
100 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500101{
Ed Tanous62598e32023-07-17 17:06:25 -0700102 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103
Ed Tanous02cad962022-06-30 16:50:15 -0700104 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700105 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500107 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108 // Update STATE only if previous State was Non_Functional and current CPU is
109 // Functional.
110 if (prevProcState == "Disabled")
111 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800112 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700114 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500115 "Enabled";
116 }
117 }
118}
119
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500120/*
121 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
122 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700123 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500124 * @param[in] cpuPresenceState CPU present or not
125 *
126 * @return None.
127 */
128inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700129 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500130 bool isCpuPresent)
131{
Ed Tanous62598e32023-07-17 17:06:25 -0700132 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500133
134 if (isCpuPresent)
135 {
136 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700137 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500138 auto* procCountPtr =
139 procCount.get_ptr<nlohmann::json::number_integer_t*>();
140 if (procCountPtr != nullptr)
141 {
142 // shouldn't be possible to be nullptr
143 *procCountPtr += 1;
144 }
145 }
146}
147
Ali Ahmed382d6472021-09-03 16:53:53 -0500148inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700149 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500150 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
151 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500152{
Ed Tanous62598e32023-07-17 17:06:25 -0700153 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500154
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200155 // TODO: Get Model
156
157 const uint16_t* coreCount = nullptr;
158
159 const bool success = sdbusplus::unpackPropertiesNoThrow(
160 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
161
162 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500163 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700164 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200165 return;
166 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500167
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200168 if (coreCount != nullptr)
169 {
170 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700171 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200172 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500173
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200174 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500175 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200176 coreCountJson = *coreCount;
177 }
178 else
179 {
180 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500181 }
182 }
183}
184
185/*
186 * @brief Get ProcessorSummary fields
187 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700188 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500189 * @param[in] service dbus service for Cpu Information
190 * @param[in] path dbus path for Cpu
191 *
192 * @return None.
193 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700194inline void
195 getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
196 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500197{
Ed Tanousac106bf2023-06-07 09:24:59 -0700198 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
199 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500200 if (ec3)
201 {
Ed Tanous62598e32023-07-17 17:06:25 -0700202 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500203 return;
204 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700205 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500206 };
207
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500208 // Get the Presence of CPU
209 sdbusplus::asio::getProperty<bool>(
210 *crow::connections::systemBus, service, path,
211 "xyz.openbmc_project.Inventory.Item", "Present",
212 std::move(getCpuPresenceState));
213
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500214 if constexpr (bmcwebEnableProcMemStatus)
215 {
216 auto getCpuFunctionalState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700217 [asyncResp](const boost::system::error_code& ec3,
218 const bool cpuFunctionalCheck) {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500219 if (ec3)
220 {
Ed Tanous62598e32023-07-17 17:06:25 -0700221 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500222 return;
223 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700224 modifyCpuFunctionalState(asyncResp, cpuFunctionalCheck);
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500225 };
Ali Ahmed382d6472021-09-03 16:53:53 -0500226
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500227 // Get the Functional State
228 sdbusplus::asio::getProperty<bool>(
229 *crow::connections::systemBus, service, path,
230 "xyz.openbmc_project.State.Decorator.OperationalStatus",
231 "Functional", std::move(getCpuFunctionalState));
232 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500233
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200234 sdbusplus::asio::getAllProperties(
235 *crow::connections::systemBus, service, path,
236 "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700237 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800238 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800239 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700240 if (ec2)
241 {
Ed Tanous62598e32023-07-17 17:06:25 -0700242 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700243 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700244 return;
245 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700246 getProcessorProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500247 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500248}
249
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500250/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500251 * @brief processMemoryProperties fields
252 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700253 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500254 * @param[in] service dbus service for memory Information
255 * @param[in] path dbus path for Memory
256 * @param[in] DBUS properties for memory
257 *
258 * @return None.
259 */
260inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700261 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500262 [[maybe_unused]] const std::string& service,
263 [[maybe_unused]] const std::string& path,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500264 const dbus::utility::DBusPropertiesMap& properties)
265{
Ed Tanous62598e32023-07-17 17:06:25 -0700266 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500267
268 if (properties.empty())
269 {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500270 if constexpr (bmcwebEnableProcMemStatus)
271 {
272 sdbusplus::asio::getProperty<bool>(
273 *crow::connections::systemBus, service, path,
274 "xyz.openbmc_project.State."
275 "Decorator.OperationalStatus",
276 "Functional",
Ed Tanousac106bf2023-06-07 09:24:59 -0700277 [asyncResp](const boost::system::error_code& ec3,
278 bool dimmState) {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500279 if (ec3)
280 {
Ed Tanous62598e32023-07-17 17:06:25 -0700281 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500282 return;
283 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700284 updateDimmProperties(asyncResp, dimmState);
Patrick Williams5a39f772023-10-20 11:20:21 -0500285 });
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500286 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500287 return;
288 }
289
290 const size_t* memorySizeInKB = nullptr;
291
292 const bool success = sdbusplus::unpackPropertiesNoThrow(
293 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
294 memorySizeInKB);
295
296 if (!success)
297 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700298 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500299 return;
300 }
301
302 if (memorySizeInKB != nullptr)
303 {
304 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700305 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500306 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500307 if (preValue == nullptr)
308 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700309 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500310 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500311 }
312 else
313 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700314 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500315 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
316 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500317 }
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500318 if constexpr (bmcwebEnableProcMemStatus)
319 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700320 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500321 "Enabled";
322 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500323 }
324}
325
326/*
327 * @brief Get getMemorySummary fields
328 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700329 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500330 * @param[in] service dbus service for memory Information
331 * @param[in] path dbus path for memory
332 *
333 * @return None.
334 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700335inline void
336 getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
337 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500338{
339 sdbusplus::asio::getAllProperties(
340 *crow::connections::systemBus, service, path,
341 "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700342 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500343 path](const boost::system::error_code& ec2,
344 const dbus::utility::DBusPropertiesMap& properties) {
345 if (ec2)
346 {
Ed Tanous62598e32023-07-17 17:06:25 -0700347 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700348 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500349 return;
350 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700351 processMemoryProperties(asyncResp, service, path, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500352 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500353}
354
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500355inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
356 const boost::system::error_code& ec,
357 const dbus::utility::DBusPropertiesMap& properties)
358{
359 if (ec)
360 {
361 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
362 messages::internalError(asyncResp->res);
363 return;
364 }
365 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
366
367 const std::string* uUID = nullptr;
368
369 const bool success = sdbusplus::unpackPropertiesNoThrow(
370 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
371
372 if (!success)
373 {
374 messages::internalError(asyncResp->res);
375 return;
376 }
377
378 if (uUID != nullptr)
379 {
380 std::string valueStr = *uUID;
381 if (valueStr.size() == 32)
382 {
383 valueStr.insert(8, 1, '-');
384 valueStr.insert(13, 1, '-');
385 valueStr.insert(18, 1, '-');
386 valueStr.insert(23, 1, '-');
387 }
388 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
389 asyncResp->res.jsonValue["UUID"] = valueStr;
390 }
391}
392
393inline void
394 afterGetInventory(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
395 const boost::system::error_code& ec,
396 const dbus::utility::DBusPropertiesMap& propertiesList)
397{
398 if (ec)
399 {
400 // doesn't have to include this
401 // interface
402 return;
403 }
404 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
405
406 const std::string* partNumber = nullptr;
407 const std::string* serialNumber = nullptr;
408 const std::string* manufacturer = nullptr;
409 const std::string* model = nullptr;
410 const std::string* subModel = nullptr;
411
412 const bool success = sdbusplus::unpackPropertiesNoThrow(
413 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
414 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
415 "Model", model, "SubModel", subModel);
416
417 if (!success)
418 {
419 messages::internalError(asyncResp->res);
420 return;
421 }
422
423 if (partNumber != nullptr)
424 {
425 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
426 }
427
428 if (serialNumber != nullptr)
429 {
430 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
431 }
432
433 if (manufacturer != nullptr)
434 {
435 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
436 }
437
438 if (model != nullptr)
439 {
440 asyncResp->res.jsonValue["Model"] = *model;
441 }
442
443 if (subModel != nullptr)
444 {
445 asyncResp->res.jsonValue["SubModel"] = *subModel;
446 }
447
448 // Grab the bios version
449 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
450 "BiosVersion", false);
451}
452
453inline void
454 afterGetAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
455 const boost::system::error_code& ec,
456 const std::string& value)
457{
458 if (ec)
459 {
460 // doesn't have to include this
461 // interface
462 return;
463 }
464
465 asyncResp->res.jsonValue["AssetTag"] = value;
466}
467
468inline void afterSystemGetSubTree(
469 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
470 const std::shared_ptr<HealthPopulate>& systemHealth,
471 const boost::system::error_code& ec,
472 const dbus::utility::MapperGetSubTreeResponse& subtree)
473{
474 if (ec)
475 {
476 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
477 messages::internalError(asyncResp->res);
478 return;
479 }
480 // Iterate over all retrieved ObjectPaths.
481 for (const std::pair<
482 std::string,
483 std::vector<std::pair<std::string, std::vector<std::string>>>>&
484 object : subtree)
485 {
486 const std::string& path = object.first;
487 BMCWEB_LOG_DEBUG("Got path: {}", path);
488 const std::vector<std::pair<std::string, std::vector<std::string>>>&
489 connectionNames = object.second;
490 if (connectionNames.empty())
491 {
492 continue;
493 }
494
495 std::shared_ptr<HealthPopulate> memoryHealth = nullptr;
496 std::shared_ptr<HealthPopulate> cpuHealth = nullptr;
497
498 if constexpr (bmcwebEnableProcMemStatus)
499 {
500 memoryHealth = std::make_shared<HealthPopulate>(
501 asyncResp, "/MemorySummary/Status"_json_pointer);
502 systemHealth->children.emplace_back(memoryHealth);
503
504 if constexpr (bmcwebEnableHealthPopulate)
505 {
506 cpuHealth = std::make_shared<HealthPopulate>(
507 asyncResp, "/ProcessorSummary/Status"_json_pointer);
508
509 systemHealth->children.emplace_back(cpuHealth);
510 }
511 }
512
513 // This is not system, so check if it's cpu, dimm, UUID or
514 // BiosVer
515 for (const auto& connection : connectionNames)
516 {
517 for (const auto& interfaceName : connection.second)
518 {
519 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
520 {
521 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
522
523 getMemorySummary(asyncResp, connection.first, path);
524
525 if constexpr (bmcwebEnableProcMemStatus)
526 {
527 memoryHealth->inventory.emplace_back(path);
528 }
529 }
530 else if (interfaceName ==
531 "xyz.openbmc_project.Inventory.Item.Cpu")
532 {
533 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
534
535 getProcessorSummary(asyncResp, connection.first, path);
536
537 if constexpr (bmcwebEnableProcMemStatus)
538 {
539 cpuHealth->inventory.emplace_back(path);
540 }
541 }
542 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
543 {
544 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
545
546 sdbusplus::asio::getAllProperties(
547 *crow::connections::systemBus, connection.first, path,
548 "xyz.openbmc_project.Common.UUID",
549 [asyncResp](const boost::system::error_code& ec3,
550 const dbus::utility::DBusPropertiesMap&
551 properties) {
552 afterGetUUID(asyncResp, ec3, properties);
553 });
554 }
555 else if (interfaceName ==
556 "xyz.openbmc_project.Inventory.Item.System")
557 {
558 sdbusplus::asio::getAllProperties(
559 *crow::connections::systemBus, connection.first, path,
560 "xyz.openbmc_project.Inventory.Decorator.Asset",
561 [asyncResp](const boost::system::error_code& ec3,
562 const dbus::utility::DBusPropertiesMap&
563 properties) {
564 afterGetInventory(asyncResp, ec3, properties);
565 });
566
567 sdbusplus::asio::getProperty<std::string>(
568 *crow::connections::systemBus, connection.first, path,
569 "xyz.openbmc_project.Inventory.Decorator."
570 "AssetTag",
571 "AssetTag",
572 std::bind_front(afterGetAssetTag, asyncResp));
573 }
574 }
575 }
576 }
577}
578
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500579/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700580 * @brief Retrieves computer system properties over dbus
581 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700582 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500583 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700584 *
585 * @return None.
586 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700587inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700588 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700589 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700590{
Ed Tanous62598e32023-07-17 17:06:25 -0700591 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800592 constexpr std::array<std::string_view, 5> interfaces = {
593 "xyz.openbmc_project.Inventory.Decorator.Asset",
594 "xyz.openbmc_project.Inventory.Item.Cpu",
595 "xyz.openbmc_project.Inventory.Item.Dimm",
596 "xyz.openbmc_project.Inventory.Item.System",
597 "xyz.openbmc_project.Common.UUID",
598 };
599 dbus::utility::getSubTree(
600 "/xyz/openbmc_project/inventory", 0, interfaces,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500601 std::bind_front(afterSystemGetSubTree, asyncResp, systemHealth));
Ed Tanous6c34de42018-08-29 13:37:36 -0700602}
603
604/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700605 * @brief Retrieves host state properties over dbus
606 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700607 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Ed Tanous6c34de42018-08-29 13:37:36 -0700608 *
609 * @return None.
610 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700611inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700612{
Ed Tanous62598e32023-07-17 17:06:25 -0700613 BMCWEB_LOG_DEBUG("Get host information.");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700614 sdbusplus::asio::getProperty<std::string>(
615 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
616 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
617 "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700618 [asyncResp](const boost::system::error_code& ec,
619 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700620 if (ec)
621 {
622 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700623 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700624 // Service not available, no error, just don't return
625 // host state info
Ed Tanous62598e32023-07-17 17:06:25 -0700626 BMCWEB_LOG_DEBUG("Service not available {}", ec);
Ed Tanous6c34de42018-08-29 13:37:36 -0700627 return;
628 }
Ed Tanous62598e32023-07-17 17:06:25 -0700629 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700630 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700631 return;
632 }
Ed Tanous66173382018-08-15 18:20:59 -0700633
Ed Tanous62598e32023-07-17 17:06:25 -0700634 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
Ed Tanous002d39b2022-05-31 08:59:27 -0700635 // Verify Host State
636 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
637 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700638 asyncResp->res.jsonValue["PowerState"] = "On";
639 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700640 }
641 else if (hostState ==
642 "xyz.openbmc_project.State.Host.HostState.Quiesced")
643 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700644 asyncResp->res.jsonValue["PowerState"] = "On";
645 asyncResp->res.jsonValue["Status"]["State"] = "Quiesced";
Ed Tanous002d39b2022-05-31 08:59:27 -0700646 }
647 else if (hostState ==
648 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
649 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700650 asyncResp->res.jsonValue["PowerState"] = "On";
651 asyncResp->res.jsonValue["Status"]["State"] = "InTest";
Ed Tanous002d39b2022-05-31 08:59:27 -0700652 }
653 else if (
654 hostState ==
655 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
656 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700657 asyncResp->res.jsonValue["PowerState"] = "PoweringOn";
658 asyncResp->res.jsonValue["Status"]["State"] = "Starting";
Ed Tanous002d39b2022-05-31 08:59:27 -0700659 }
660 else if (hostState ==
661 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
662 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700663 asyncResp->res.jsonValue["PowerState"] = "PoweringOff";
664 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700665 }
666 else
667 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700668 asyncResp->res.jsonValue["PowerState"] = "Off";
669 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700670 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500671 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700672}
673
674/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500675 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530676 *
677 * @param[in] dbusSource The boot source in DBUS speak.
678 *
679 * @return Returns as a string, the boot source in Redfish terms. If translation
680 * cannot be done, returns an empty string.
681 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000682inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530683{
684 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
685 {
686 return "None";
687 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700688 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530689 {
690 return "Hdd";
691 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700692 if (dbusSource ==
693 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530694 {
695 return "Cd";
696 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700697 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530698 {
699 return "Pxe";
700 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700701 if (dbusSource ==
702 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700703 {
704 return "Usb";
705 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700706 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530707}
708
709/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300710 * @brief Translates boot type DBUS property value to redfish.
711 *
712 * @param[in] dbusType The boot type in DBUS speak.
713 *
714 * @return Returns as a string, the boot type in Redfish terms. If translation
715 * cannot be done, returns an empty string.
716 */
717inline std::string dbusToRfBootType(const std::string& dbusType)
718{
719 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
720 {
721 return "Legacy";
722 }
723 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
724 {
725 return "UEFI";
726 }
727 return "";
728}
729
730/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500731 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530732 *
733 * @param[in] dbusMode The boot mode in DBUS speak.
734 *
735 * @return Returns as a string, the boot mode in Redfish terms. If translation
736 * cannot be done, returns an empty string.
737 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000738inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530739{
740 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
741 {
742 return "None";
743 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700744 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530745 {
746 return "Diags";
747 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700748 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530749 {
750 return "BiosSetup";
751 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700752 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530753}
754
755/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600756 * @brief Translates boot progress DBUS property value to redfish.
757 *
758 * @param[in] dbusBootProgress The boot progress in DBUS speak.
759 *
760 * @return Returns as a string, the boot progress in Redfish terms. If
761 * translation cannot be done, returns "None".
762 */
763inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
764{
765 // Now convert the D-Bus BootProgress to the appropriate Redfish
766 // enum
767 std::string rfBpLastState = "None";
768 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
769 "ProgressStages.Unspecified")
770 {
771 rfBpLastState = "None";
772 }
773 else if (dbusBootProgress ==
774 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
775 "PrimaryProcInit")
776 {
777 rfBpLastState = "PrimaryProcessorInitializationStarted";
778 }
779 else if (dbusBootProgress ==
780 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
781 "BusInit")
782 {
783 rfBpLastState = "BusInitializationStarted";
784 }
785 else if (dbusBootProgress ==
786 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
787 "MemoryInit")
788 {
789 rfBpLastState = "MemoryInitializationStarted";
790 }
791 else if (dbusBootProgress ==
792 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
793 "SecondaryProcInit")
794 {
795 rfBpLastState = "SecondaryProcessorInitializationStarted";
796 }
797 else if (dbusBootProgress ==
798 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
799 "PCIInit")
800 {
801 rfBpLastState = "PCIResourceConfigStarted";
802 }
803 else if (dbusBootProgress ==
804 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
805 "SystemSetup")
806 {
807 rfBpLastState = "SetupEntered";
808 }
809 else if (dbusBootProgress ==
810 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
811 "SystemInitComplete")
812 {
813 rfBpLastState = "SystemHardwareInitializationComplete";
814 }
815 else if (dbusBootProgress ==
816 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
817 "OSStart")
818 {
819 rfBpLastState = "OSBootStarted";
820 }
821 else if (dbusBootProgress ==
822 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
823 "OSRunning")
824 {
825 rfBpLastState = "OSRunning";
826 }
827 else
828 {
Ed Tanous62598e32023-07-17 17:06:25 -0700829 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600830 // Just return the default
831 }
832 return rfBpLastState;
833}
834
835/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500836 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530837 *
838 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700839 * @param[out] bootSource The DBus source
840 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530841 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700842 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530843 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700844inline int
845 assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
846 const std::string& rfSource, std::string& bootSource,
847 std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530848{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300849 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
850 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700851
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530852 if (rfSource == "None")
853 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700854 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530855 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700856 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530857 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700858 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
859 }
860 else if (rfSource == "Hdd")
861 {
862 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
863 }
864 else if (rfSource == "Diags")
865 {
866 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
867 }
868 else if (rfSource == "Cd")
869 {
870 bootSource =
871 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
872 }
873 else if (rfSource == "BiosSetup")
874 {
875 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530876 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700877 else if (rfSource == "Usb")
878 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700879 bootSource =
880 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700881 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530882 else
883 {
Ed Tanous62598e32023-07-17 17:06:25 -0700884 BMCWEB_LOG_DEBUG(
885 "Invalid property value for BootSourceOverrideTarget: {}",
886 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700887 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700888 "BootSourceTargetOverride");
889 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530890 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700891 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530892}
Ali Ahmed19817712021-06-29 17:01:52 -0500893
Andrew Geissler978b8802020-11-19 13:36:40 -0600894/**
895 * @brief Retrieves boot progress of the system
896 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700897 * @param[in] asyncResp Shared pointer for generating response message.
Andrew Geissler978b8802020-11-19 13:36:40 -0600898 *
899 * @return None.
900 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700901inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600902{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700903 sdbusplus::asio::getProperty<std::string>(
904 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
905 "/xyz/openbmc_project/state/host0",
906 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700907 [asyncResp](const boost::system::error_code& ec,
908 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700909 if (ec)
910 {
911 // BootProgress is an optional object so just do nothing if
912 // not found
913 return;
914 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600915
Ed Tanous62598e32023-07-17 17:06:25 -0700916 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600917
Ed Tanousac106bf2023-06-07 09:24:59 -0700918 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700919 dbusToRfBootProgress(bootProgressStr);
Patrick Williams5a39f772023-10-20 11:20:21 -0500920 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600921}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530922
923/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000924 * @brief Retrieves boot progress Last Update of the system
925 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700926 * @param[in] asyncResp Shared pointer for generating response message.
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000927 *
928 * @return None.
929 */
930inline void getBootProgressLastStateTime(
Ed Tanousac106bf2023-06-07 09:24:59 -0700931 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000932{
933 sdbusplus::asio::getProperty<uint64_t>(
934 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
935 "/xyz/openbmc_project/state/host0",
936 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700937 [asyncResp](const boost::system::error_code& ec,
938 const uint64_t lastStateTime) {
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000939 if (ec)
940 {
Ed Tanous62598e32023-07-17 17:06:25 -0700941 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000942 return;
943 }
944
945 // BootProgressLastUpdate is the last time the BootProgress property
946 // was updated. The time is the Epoch time, number of microseconds
947 // since 1 Jan 1970 00::00::00 UTC."
948 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
949 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
950
951 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -0700952 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000953 redfish::time_utils::getDateTimeUintUs(lastStateTime);
Patrick Williams5a39f772023-10-20 11:20:21 -0500954 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000955}
956
957/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300958 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300959 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700960 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300961 *
962 * @return None.
963 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300964
Ed Tanousac106bf2023-06-07 09:24:59 -0700965inline void
966 getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300967{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700968 sdbusplus::asio::getProperty<std::string>(
969 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
970 "/xyz/openbmc_project/control/host0/boot",
971 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700972 [asyncResp](const boost::system::error_code& ec,
973 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700974 if (ec)
975 {
976 // not an error, don't have to have the interface
977 return;
978 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300979
Ed Tanous62598e32023-07-17 17:06:25 -0700980 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300981
Ed Tanousac106bf2023-06-07 09:24:59 -0700982 asyncResp->res
983 .jsonValue["Boot"]
984 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700985 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300986
Ed Tanous002d39b2022-05-31 08:59:27 -0700987 auto rfType = dbusToRfBootType(bootType);
988 if (rfType.empty())
989 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700990 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700991 return;
992 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300993
Ed Tanousac106bf2023-06-07 09:24:59 -0700994 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Patrick Williams5a39f772023-10-20 11:20:21 -0500995 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300996}
997
998/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300999 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001001 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301002 *
1003 * @return None.
1004 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001005
Ed Tanousac106bf2023-06-07 09:24:59 -07001006inline void
1007 getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001009 sdbusplus::asio::getProperty<std::string>(
1010 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1011 "/xyz/openbmc_project/control/host0/boot",
1012 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -07001013 [asyncResp](const boost::system::error_code& ec,
1014 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001015 if (ec)
1016 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001017 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001018 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001019 return;
1020 }
1021
Ed Tanous62598e32023-07-17 17:06:25 -07001022 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
Ed Tanous002d39b2022-05-31 08:59:27 -07001023
Ed Tanousac106bf2023-06-07 09:24:59 -07001024 asyncResp->res
Ed Tanous002d39b2022-05-31 08:59:27 -07001025 .jsonValue["Boot"]
1026 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
1027 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
1028
1029 if (bootModeStr !=
1030 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1031 {
1032 auto rfMode = dbusToRfBootMode(bootModeStr);
1033 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001035 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001036 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301037 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001038 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001039 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301040}
1041
1042/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001045 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301046 *
1047 * @return None.
1048 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001049
1050inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001051 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301052{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001053 sdbusplus::asio::getProperty<std::string>(
1054 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1055 "/xyz/openbmc_project/control/host0/boot",
1056 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanousac106bf2023-06-07 09:24:59 -07001057 [asyncResp](const boost::system::error_code& ec,
1058 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001059 if (ec)
1060 {
Nan Zhou5ef735c2022-06-22 05:24:21 +00001061 if (ec.value() == boost::asio::error::host_unreachable)
1062 {
1063 return;
1064 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001065 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001066 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001067 return;
1068 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301069
Ed Tanous62598e32023-07-17 17:06:25 -07001070 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301071
Ed Tanous002d39b2022-05-31 08:59:27 -07001072 auto rfSource = dbusToRfBootSource(bootSourceStr);
1073 if (!rfSource.empty())
1074 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001075 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1076 rfSource;
Ed Tanous002d39b2022-05-31 08:59:27 -07001077 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001078
Ed Tanous002d39b2022-05-31 08:59:27 -07001079 // Get BootMode as BootSourceOverrideTarget is constructed
1080 // from both BootSource and BootMode
Ed Tanousac106bf2023-06-07 09:24:59 -07001081 getBootOverrideMode(asyncResp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001082 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301083}
1084
1085/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001086 * @brief This functions abstracts all the logic behind getting a
1087 * "BootSourceOverrideEnabled" property from an overall boot override enable
1088 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301089 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001090 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301091 *
1092 * @return None.
1093 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301094
Ed Tanousac106bf2023-06-07 09:24:59 -07001095inline void processBootOverrideEnable(
1096 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1097 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001098{
1099 if (!bootOverrideEnableSetting)
1100 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001101 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1102 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001103 return;
1104 }
1105
1106 // If boot source override is enabled, we need to check 'one_time'
1107 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001108 sdbusplus::asio::getProperty<bool>(
1109 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1110 "/xyz/openbmc_project/control/host0/boot/one_time",
1111 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001112 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001113 if (ec)
1114 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001115 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001116 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001117 return;
1118 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301119
Ed Tanous002d39b2022-05-31 08:59:27 -07001120 if (oneTimeSetting)
1121 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001122 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1123 "Once";
Ed Tanous002d39b2022-05-31 08:59:27 -07001124 }
1125 else
1126 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001127 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001128 "Continuous";
1129 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001130 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301131}
1132
1133/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001134 * @brief Retrieves boot override enable over DBUS
1135 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001136 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001137 *
1138 * @return None.
1139 */
1140
1141inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001142 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001143{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001144 sdbusplus::asio::getProperty<bool>(
1145 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1146 "/xyz/openbmc_project/control/host0/boot",
1147 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001148 [asyncResp](const boost::system::error_code& ec,
1149 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001150 if (ec)
1151 {
Nan Zhou5ef735c2022-06-22 05:24:21 +00001152 if (ec.value() == boost::asio::error::host_unreachable)
1153 {
1154 return;
1155 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001156 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001157 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001158 return;
1159 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001160
Ed Tanousac106bf2023-06-07 09:24:59 -07001161 processBootOverrideEnable(asyncResp, bootOverrideEnable);
Patrick Williams5a39f772023-10-20 11:20:21 -05001162 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001163}
1164
1165/**
1166 * @brief Retrieves boot source override properties
1167 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001168 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001169 *
1170 * @return None.
1171 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001172inline void
1173 getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001174{
Ed Tanous62598e32023-07-17 17:06:25 -07001175 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001176
Ed Tanousac106bf2023-06-07 09:24:59 -07001177 getBootOverrideSource(asyncResp);
1178 getBootOverrideType(asyncResp);
1179 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001180}
1181
1182/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001183 * @brief Retrieves the Last Reset Time
1184 *
1185 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1186 * and power off. Even though this is the "system" Redfish object look at the
1187 * chassis D-Bus interface for the LastStateChangeTime since this has the
1188 * last power operation time.
1189 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001190 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001191 *
1192 * @return None.
1193 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001194inline void
1195 getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001196{
Ed Tanous62598e32023-07-17 17:06:25 -07001197 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001198
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001199 sdbusplus::asio::getProperty<uint64_t>(
1200 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1201 "/xyz/openbmc_project/state/chassis0",
1202 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001203 [asyncResp](const boost::system::error_code& ec,
1204 uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001205 if (ec)
1206 {
Ed Tanous62598e32023-07-17 17:06:25 -07001207 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001208 return;
1209 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001210
Ed Tanous002d39b2022-05-31 08:59:27 -07001211 // LastStateChangeTime is epoch time, in milliseconds
1212 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1213 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001214
Ed Tanous002d39b2022-05-31 08:59:27 -07001215 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -07001216 asyncResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001217 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001218 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001219}
1220
1221/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001222 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1223 *
1224 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1225 * corresponding property "AttemptsLeft" that keeps track of the amount of
1226 * automatic retry attempts left are hosted in phosphor-state-manager through
1227 * dbus.
1228 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001229 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001230 *
1231 * @return None.
1232 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001233inline void getAutomaticRebootAttempts(
1234 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001235{
Ed Tanous62598e32023-07-17 17:06:25 -07001236 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001237
1238 sdbusplus::asio::getAllProperties(
1239 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1240 "/xyz/openbmc_project/state/host0",
1241 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001242 [asyncResp{asyncResp}](
1243 const boost::system::error_code& ec,
1244 const dbus::utility::DBusPropertiesMap& propertiesList) {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001245 if (ec)
1246 {
1247 if (ec.value() != EBADR)
1248 {
Ed Tanous62598e32023-07-17 17:06:25 -07001249 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001250 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001251 }
1252 return;
1253 }
1254
1255 const uint32_t* attemptsLeft = nullptr;
1256 const uint32_t* retryAttempts = nullptr;
1257
1258 const bool success = sdbusplus::unpackPropertiesNoThrow(
1259 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1260 attemptsLeft, "RetryAttempts", retryAttempts);
1261
1262 if (!success)
1263 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001264 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001265 return;
1266 }
1267
1268 if (attemptsLeft != nullptr)
1269 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001270 asyncResp->res
1271 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001272 *attemptsLeft;
1273 }
1274
1275 if (retryAttempts != nullptr)
1276 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001277 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001278 *retryAttempts;
1279 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001280 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001281}
1282
1283/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001284 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1285 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001286 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001287 *
1288 * @return None.
1289 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001290inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001291 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001292{
Ed Tanous62598e32023-07-17 17:06:25 -07001293 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001294
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001295 sdbusplus::asio::getProperty<bool>(
1296 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1297 "/xyz/openbmc_project/control/host0/auto_reboot",
1298 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001299 [asyncResp](const boost::system::error_code& ec,
1300 bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001301 if (ec)
1302 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001303 if (ec.value() != EBADR)
1304 {
Ed Tanous62598e32023-07-17 17:06:25 -07001305 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001306 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001307 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001308 return;
1309 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001310
Ed Tanous62598e32023-07-17 17:06:25 -07001311 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
Ed Tanous002d39b2022-05-31 08:59:27 -07001312 if (autoRebootEnabled)
1313 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001314 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001315 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001316 }
1317 else
1318 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001319 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1320 "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -07001321 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001322 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001323
Ed Tanous002d39b2022-05-31 08:59:27 -07001324 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1325 // and RetryAttempts. OpenBMC only supports Disabled and
1326 // RetryAttempts.
Ed Tanousac106bf2023-06-07 09:24:59 -07001327 asyncResp->res
1328 .jsonValue["Boot"]["AutomaticRetryConfig@Redfish.AllowableValues"] =
1329 {"Disabled", "RetryAttempts"};
Patrick Williams5a39f772023-10-20 11:20:21 -05001330 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001331}
1332
1333/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001334 * @brief Sets RetryAttempts
1335 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001336 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001337 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1338 *
1339 *@return None.
1340 */
1341
Ed Tanousac106bf2023-06-07 09:24:59 -07001342inline void setAutomaticRetryAttempts(
1343 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1344 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001345{
Ed Tanous62598e32023-07-17 17:06:25 -07001346 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
George Liu9ae226f2023-06-21 17:56:46 +08001347 sdbusplus::asio::setProperty(
1348 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1349 "/xyz/openbmc_project/state/host0",
Corey Hardesty797d5da2022-04-26 17:54:52 +08001350 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
George Liu9ae226f2023-06-21 17:56:46 +08001351 retryAttempts, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -05001352 if (ec)
1353 {
1354 BMCWEB_LOG_ERROR(
1355 "DBUS response error: Set setAutomaticRetryAttempts{}", ec);
1356 messages::internalError(asyncResp->res);
1357 return;
1358 }
1359 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001360}
1361
Ed Tanous8d69c662023-06-21 10:29:06 -07001362inline computer_system::PowerRestorePolicyTypes
1363 redfishPowerRestorePolicyFromDbus(std::string_view value)
1364{
1365 if (value ==
1366 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1367 {
1368 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1369 }
1370 if (value ==
1371 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1372 {
1373 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1374 }
1375 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001376 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001377 {
1378 return computer_system::PowerRestorePolicyTypes::LastState;
1379 }
1380 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1381 {
1382 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1383 }
1384 return computer_system::PowerRestorePolicyTypes::Invalid;
1385}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001386/**
George Liuc6a620f2020-04-10 17:18:11 +08001387 * @brief Retrieves power restore policy over DBUS.
1388 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001389 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001390 *
1391 * @return None.
1392 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001393inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001394 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001395{
Ed Tanous62598e32023-07-17 17:06:25 -07001396 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001397
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001398 sdbusplus::asio::getProperty<std::string>(
1399 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1400 "/xyz/openbmc_project/control/host0/power_restore_policy",
1401 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001402 [asyncResp](const boost::system::error_code& ec,
1403 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001404 if (ec)
1405 {
Ed Tanous62598e32023-07-17 17:06:25 -07001406 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001407 return;
1408 }
Ed Tanous8d69c662023-06-21 10:29:06 -07001409 computer_system::PowerRestorePolicyTypes restore =
1410 redfishPowerRestorePolicyFromDbus(policy);
1411 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -07001412 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001413 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001414 return;
1415 }
George Liuc6a620f2020-04-10 17:18:11 +08001416
Ed Tanous8d69c662023-06-21 10:29:06 -07001417 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
Patrick Williams5a39f772023-10-20 11:20:21 -05001418 });
George Liuc6a620f2020-04-10 17:18:11 +08001419}
1420
1421/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001422 * @brief Stop Boot On Fault over DBUS.
1423 *
1424 * @param[in] asyncResp Shared pointer for generating response message.
1425 *
1426 * @return None.
1427 */
1428inline void
1429 getStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1430{
Ed Tanous62598e32023-07-17 17:06:25 -07001431 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001432
1433 sdbusplus::asio::getProperty<bool>(
1434 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1435 "/xyz/openbmc_project/logging/settings",
1436 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1437 [asyncResp](const boost::system::error_code& ec, bool value) {
1438 if (ec)
1439 {
1440 if (ec.value() != EBADR)
1441 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001442 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001443 messages::internalError(asyncResp->res);
1444 }
1445 return;
1446 }
1447
1448 if (value)
1449 {
1450 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "AnyFault";
1451 }
1452 else
1453 {
1454 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "Never";
1455 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001456 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001457}
1458
1459/**
Ali Ahmed19817712021-06-29 17:01:52 -05001460 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1461 * TPM is required for booting the host.
1462 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001463 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001464 *
1465 * @return None.
1466 */
1467inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001468 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001469{
Ed Tanous62598e32023-07-17 17:06:25 -07001470 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001471 constexpr std::array<std::string_view, 1> interfaces = {
1472 "xyz.openbmc_project.Control.TPM.Policy"};
1473 dbus::utility::getSubTree(
1474 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001475 [asyncResp](const boost::system::error_code& ec,
1476 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001477 if (ec)
1478 {
Ed Tanous62598e32023-07-17 17:06:25 -07001479 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}",
1480 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001481 // This is an optional D-Bus object so just return if
1482 // error occurs
1483 return;
1484 }
1485 if (subtree.empty())
1486 {
1487 // As noted above, this is an optional interface so just return
1488 // if there is no instance found
1489 return;
1490 }
1491
1492 /* When there is more than one TPMEnable object... */
1493 if (subtree.size() > 1)
1494 {
Ed Tanous62598e32023-07-17 17:06:25 -07001495 BMCWEB_LOG_DEBUG(
1496 "DBUS response has more than 1 TPM Enable object:{}",
1497 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001498 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001499 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001500 return;
1501 }
1502
1503 // Make sure the Dbus response map has a service and objectPath
1504 // field
1505 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1506 {
Ed Tanous62598e32023-07-17 17:06:25 -07001507 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001508 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001509 return;
1510 }
1511
1512 const std::string& path = subtree[0].first;
1513 const std::string& serv = subtree[0].second.begin()->first;
1514
1515 // Valid TPM Enable object found, now reading the current value
1516 sdbusplus::asio::getProperty<bool>(
1517 *crow::connections::systemBus, serv, path,
1518 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanousac106bf2023-06-07 09:24:59 -07001519 [asyncResp](const boost::system::error_code& ec2,
1520 bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001521 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001522 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001523 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001524 ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001525 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001526 return;
1527 }
1528
Ed Tanous002d39b2022-05-31 08:59:27 -07001529 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001530 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001531 asyncResp->res
1532 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001533 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001534 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001535 else
1536 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001537 asyncResp->res
1538 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001539 "Disabled";
1540 }
George Liue99073f2022-12-09 11:06:16 +08001541 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001542 });
Ali Ahmed19817712021-06-29 17:01:52 -05001543}
1544
1545/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001546 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1547 * TPM is required for booting the host.
1548 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001549 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001550 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1551 *
1552 * @return None.
1553 */
1554inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001555 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001556{
Ed Tanous62598e32023-07-17 17:06:25 -07001557 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001558 constexpr std::array<std::string_view, 1> interfaces = {
1559 "xyz.openbmc_project.Control.TPM.Policy"};
1560 dbus::utility::getSubTree(
1561 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001562 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001563 tpmRequired](const boost::system::error_code& ec,
1564 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001565 if (ec)
1566 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001567 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001568 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001569 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001570 return;
1571 }
1572 if (subtree.empty())
1573 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001574 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07001575 "TrustedModuleRequiredToBoot");
1576 return;
1577 }
1578
1579 /* When there is more than one TPMEnable object... */
1580 if (subtree.size() > 1)
1581 {
Ed Tanous62598e32023-07-17 17:06:25 -07001582 BMCWEB_LOG_DEBUG(
1583 "DBUS response has more than 1 TPM Enable object:{}",
1584 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001585 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001586 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001587 return;
1588 }
1589
1590 // Make sure the Dbus response map has a service and objectPath
1591 // field
1592 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1593 {
Ed Tanous62598e32023-07-17 17:06:25 -07001594 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001595 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001596 return;
1597 }
1598
1599 const std::string& path = subtree[0].first;
1600 const std::string& serv = subtree[0].second.begin()->first;
1601
1602 if (serv.empty())
1603 {
Ed Tanous62598e32023-07-17 17:06:25 -07001604 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001605 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001606 return;
1607 }
1608
1609 // Valid TPM Enable object found, now setting the value
George Liu9ae226f2023-06-21 17:56:46 +08001610 sdbusplus::asio::setProperty(
1611 *crow::connections::systemBus, serv, path,
1612 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable", tpmRequired,
Ed Tanousac106bf2023-06-07 09:24:59 -07001613 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001614 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001615 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001616 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07001617 "DBUS response error: Set TrustedModuleRequiredToBoot{}",
1618 ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001619 messages::internalError(asyncResp->res);
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001620 return;
1621 }
Ed Tanous62598e32023-07-17 17:06:25 -07001622 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot done.");
George Liue99073f2022-12-09 11:06:16 +08001623 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001624 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001625}
1626
1627/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301628 * @brief Sets boot properties into DBUS object(s).
1629 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001630 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001631 * @param[in] bootType The boot type to set.
1632 * @return Integer error code.
1633 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001634inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001635 const std::optional<std::string>& bootType)
1636{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001637 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001638
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001639 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001640 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001641 return;
1642 }
1643
1644 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001645 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001646 // Figure out which DBUS interface and property to use
1647 if (*bootType == "Legacy")
1648 {
1649 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1650 }
1651 else if (*bootType == "UEFI")
1652 {
1653 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1654 }
1655 else
1656 {
Ed Tanous62598e32023-07-17 17:06:25 -07001657 BMCWEB_LOG_DEBUG("Invalid property value for "
1658 "BootSourceOverrideMode: {}",
1659 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001660 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001661 "BootSourceOverrideMode");
1662 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001663 }
1664
1665 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001666 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001667
George Liu9ae226f2023-06-21 17:56:46 +08001668 sdbusplus::asio::setProperty(
1669 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1670 "/xyz/openbmc_project/control/host0/boot",
1671 "xyz.openbmc_project.Control.Boot.Type", "BootType", bootTypeStr,
Ed Tanousac106bf2023-06-07 09:24:59 -07001672 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001673 if (ec)
1674 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001675 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001676 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001677 messages::resourceNotFound(asyncResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001678 return;
1679 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001680 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001681 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001682 return;
1683 }
Ed Tanous62598e32023-07-17 17:06:25 -07001684 BMCWEB_LOG_DEBUG("Boot type update done.");
Patrick Williams5a39f772023-10-20 11:20:21 -05001685 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001686}
1687
1688/**
1689 * @brief Sets boot properties into DBUS object(s).
1690 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001691 * @param[in] asyncResp Shared pointer for generating response
1692 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001693 * @param[in] bootType The boot type to set.
1694 * @return Integer error code.
1695 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001696inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001697 const std::optional<std::string>& bootEnable)
1698{
1699 if (!bootEnable)
1700 {
1701 return;
1702 }
1703 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001704 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001705
1706 bool bootOverrideEnable = false;
1707 bool bootOverridePersistent = false;
1708 // Figure out which DBUS interface and property to use
1709 if (*bootEnable == "Disabled")
1710 {
1711 bootOverrideEnable = false;
1712 }
1713 else if (*bootEnable == "Once")
1714 {
1715 bootOverrideEnable = true;
1716 bootOverridePersistent = false;
1717 }
1718 else if (*bootEnable == "Continuous")
1719 {
1720 bootOverrideEnable = true;
1721 bootOverridePersistent = true;
1722 }
1723 else
1724 {
Ed Tanous62598e32023-07-17 17:06:25 -07001725 BMCWEB_LOG_DEBUG(
1726 "Invalid property value for BootSourceOverrideEnabled: {}",
1727 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001728 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001729 "BootSourceOverrideEnabled");
1730 return;
1731 }
1732
1733 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001734 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001735
George Liu9ae226f2023-06-21 17:56:46 +08001736 sdbusplus::asio::setProperty(
1737 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1738 "/xyz/openbmc_project/control/host0/boot",
1739 "xyz.openbmc_project.Object.Enable", "Enabled", bootOverrideEnable,
Ed Tanousac106bf2023-06-07 09:24:59 -07001740 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001741 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001742 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001743 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001744 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001745 return;
1746 }
Ed Tanous62598e32023-07-17 17:06:25 -07001747 BMCWEB_LOG_DEBUG("Boot override enable update done.");
Patrick Williams5a39f772023-10-20 11:20:21 -05001748 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001749
1750 if (!bootOverrideEnable)
1751 {
1752 return;
1753 }
1754
1755 // In case boot override is enabled we need to set correct value for the
1756 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001757 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1758 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001759
George Liu9ae226f2023-06-21 17:56:46 +08001760 sdbusplus::asio::setProperty(
1761 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1762 "/xyz/openbmc_project/control/host0/boot/one_time",
1763 "xyz.openbmc_project.Object.Enable", "Enabled", !bootOverridePersistent,
Ed Tanousac106bf2023-06-07 09:24:59 -07001764 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001765 if (ec)
1766 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001767 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001768 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001769 return;
1770 }
Ed Tanous62598e32023-07-17 17:06:25 -07001771 BMCWEB_LOG_DEBUG("Boot one_time update done.");
Patrick Williams5a39f772023-10-20 11:20:21 -05001772 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001773}
1774
1775/**
1776 * @brief Sets boot properties into DBUS object(s).
1777 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001778 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301779 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301780 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001781 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301782 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001783inline void
1784 setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1785 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301786{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001787 std::string bootSourceStr;
1788 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001789
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001790 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301791 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001792 return;
1793 }
1794
1795 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001796 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001797 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001798 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1799 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001800 {
Ed Tanous62598e32023-07-17 17:06:25 -07001801 BMCWEB_LOG_DEBUG(
1802 "Invalid property value for BootSourceOverrideTarget: {}",
1803 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001804 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001805 "BootSourceTargetOverride");
1806 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001807 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301808
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001809 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001810 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1811 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001812
George Liu9ae226f2023-06-21 17:56:46 +08001813 sdbusplus::asio::setProperty(
1814 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1815 "/xyz/openbmc_project/control/host0/boot",
1816 "xyz.openbmc_project.Control.Boot.Source", "BootSource", bootSourceStr,
Ed Tanousac106bf2023-06-07 09:24:59 -07001817 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001818 if (ec)
1819 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001820 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001821 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001822 return;
1823 }
Ed Tanous62598e32023-07-17 17:06:25 -07001824 BMCWEB_LOG_DEBUG("Boot source update done.");
Patrick Williams5a39f772023-10-20 11:20:21 -05001825 });
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001826
George Liu9ae226f2023-06-21 17:56:46 +08001827 sdbusplus::asio::setProperty(
1828 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1829 "/xyz/openbmc_project/control/host0/boot",
1830 "xyz.openbmc_project.Control.Boot.Mode", "BootMode", bootModeStr,
Ed Tanousac106bf2023-06-07 09:24:59 -07001831 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001832 if (ec)
1833 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001834 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001835 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001836 return;
1837 }
Ed Tanous62598e32023-07-17 17:06:25 -07001838 BMCWEB_LOG_DEBUG("Boot mode update done.");
Patrick Williams5a39f772023-10-20 11:20:21 -05001839 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001840}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001841
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001842/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001843 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301844 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001845 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301846 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001847 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301848 * @param[in] bootEnable The boot override enable from incoming RF request.
1849 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001850 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301851 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001852
Ed Tanousac106bf2023-06-07 09:24:59 -07001853inline void
1854 setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1855 const std::optional<std::string>& bootSource,
1856 const std::optional<std::string>& bootType,
1857 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301858{
Ed Tanous62598e32023-07-17 17:06:25 -07001859 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301860
Ed Tanousac106bf2023-06-07 09:24:59 -07001861 setBootModeOrSource(asyncResp, bootSource);
1862 setBootType(asyncResp, bootType);
1863 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301864}
1865
George Liuc6a620f2020-04-10 17:18:11 +08001866/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001867 * @brief Sets AssetTag
1868 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001869 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001870 * @param[in] assetTag "AssetTag" from request.
1871 *
1872 * @return None.
1873 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001874inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001875 const std::string& assetTag)
1876{
George Liue99073f2022-12-09 11:06:16 +08001877 constexpr std::array<std::string_view, 1> interfaces = {
1878 "xyz.openbmc_project.Inventory.Item.System"};
1879 dbus::utility::getSubTree(
1880 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001881 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001882 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001883 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001884 if (ec)
1885 {
Ed Tanous62598e32023-07-17 17:06:25 -07001886 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001887 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001888 return;
1889 }
1890 if (subtree.empty())
1891 {
Ed Tanous62598e32023-07-17 17:06:25 -07001892 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001893 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001894 return;
1895 }
1896 // Assume only 1 system D-Bus object
1897 // Throw an error if there is more than 1
1898 if (subtree.size() > 1)
1899 {
Ed Tanous62598e32023-07-17 17:06:25 -07001900 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001901 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001902 return;
1903 }
1904 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1905 {
Ed Tanous62598e32023-07-17 17:06:25 -07001906 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001907 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001908 return;
1909 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001910
Ed Tanous002d39b2022-05-31 08:59:27 -07001911 const std::string& path = subtree[0].first;
1912 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001913
Ed Tanous002d39b2022-05-31 08:59:27 -07001914 if (service.empty())
1915 {
Ed Tanous62598e32023-07-17 17:06:25 -07001916 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001917 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001918 return;
1919 }
1920
George Liu9ae226f2023-06-21 17:56:46 +08001921 sdbusplus::asio::setProperty(
1922 *crow::connections::systemBus, service, path,
Ed Tanous002d39b2022-05-31 08:59:27 -07001923 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
George Liu9ae226f2023-06-21 17:56:46 +08001924 assetTag, [asyncResp](const boost::system::error_code& ec2) {
Patrick Williams5a39f772023-10-20 11:20:21 -05001925 if (ec2)
1926 {
1927 BMCWEB_LOG_ERROR("D-Bus response error on AssetTag Set {}",
1928 ec2);
1929 messages::internalError(asyncResp->res);
1930 return;
1931 }
George Liue99073f2022-12-09 11:06:16 +08001932 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001933 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001934}
1935
1936/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001937 * @brief Validate the specified stopBootOnFault is valid and return the
1938 * stopBootOnFault name associated with that string
1939 *
1940 * @param[in] stopBootOnFaultString String representing the desired
1941 * stopBootOnFault
1942 *
1943 * @return stopBootOnFault value or empty if incoming value is not valid
1944 */
1945inline std::optional<bool>
1946 validstopBootOnFault(const std::string& stopBootOnFaultString)
1947{
1948 if (stopBootOnFaultString == "AnyFault")
1949 {
1950 return true;
1951 }
1952
1953 if (stopBootOnFaultString == "Never")
1954 {
1955 return false;
1956 }
1957
1958 return std::nullopt;
1959}
1960
1961/**
1962 * @brief Sets stopBootOnFault
1963 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001964 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001965 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1966 *
1967 * @return None.
1968 */
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001969inline void
1970 setStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1971 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001972{
Ed Tanous62598e32023-07-17 17:06:25 -07001973 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001974
1975 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1976 if (!stopBootEnabled)
1977 {
Ed Tanous62598e32023-07-17 17:06:25 -07001978 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1979 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001980 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001981 "StopBootOnFault");
1982 return;
1983 }
1984
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001985 sdbusplus::asio::setProperty(
1986 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1987 "/xyz/openbmc_project/logging/settings",
1988 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1989 *stopBootEnabled, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -05001990 if (ec)
1991 {
1992 if (ec.value() != EBADR)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001993 {
Patrick Williams5a39f772023-10-20 11:20:21 -05001994 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1995 messages::internalError(asyncResp->res);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001996 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001997 return;
1998 }
1999 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08002000}
2001
2002/**
Gunnar Mills69f35302020-05-17 16:06:31 -05002003 * @brief Sets automaticRetry (Auto Reboot)
2004 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002005 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05002006 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
2007 *
2008 * @return None.
2009 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002010inline void
2011 setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2012 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05002013{
Ed Tanous62598e32023-07-17 17:06:25 -07002014 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05002015
2016 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08002017 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05002018
2019 if (automaticRetryConfig == "Disabled")
2020 {
2021 autoRebootEnabled = false;
2022 }
2023 else if (automaticRetryConfig == "RetryAttempts")
2024 {
2025 autoRebootEnabled = true;
2026 }
2027 else
2028 {
Ed Tanous62598e32023-07-17 17:06:25 -07002029 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
2030 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07002031 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05002032 "AutomaticRetryConfig");
2033 return;
2034 }
2035
George Liu9ae226f2023-06-21 17:56:46 +08002036 sdbusplus::asio::setProperty(
2037 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
Gunnar Mills69f35302020-05-17 16:06:31 -05002038 "/xyz/openbmc_project/control/host0/auto_reboot",
Gunnar Mills69f35302020-05-17 16:06:31 -05002039 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
George Liu9ae226f2023-06-21 17:56:46 +08002040 autoRebootEnabled, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -05002041 if (ec)
2042 {
2043 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
2044 messages::internalError(asyncResp->res);
2045 return;
2046 }
2047 });
Gunnar Mills69f35302020-05-17 16:06:31 -05002048}
2049
Ed Tanous8d69c662023-06-21 10:29:06 -07002050inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
2051{
2052 if (policy == "AlwaysOn")
2053 {
2054 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
2055 }
2056 if (policy == "AlwaysOff")
2057 {
2058 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
2059 }
2060 if (policy == "LastState")
2061 {
2062 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
2063 }
2064 return "";
2065}
2066
Gunnar Mills69f35302020-05-17 16:06:31 -05002067/**
George Liuc6a620f2020-04-10 17:18:11 +08002068 * @brief Sets power restore policy properties.
2069 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002070 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08002071 * @param[in] policy power restore policy properties from request.
2072 *
2073 * @return None.
2074 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002075inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002076 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous8d69c662023-06-21 10:29:06 -07002077 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08002078{
Ed Tanous62598e32023-07-17 17:06:25 -07002079 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08002080
Ed Tanous8d69c662023-06-21 10:29:06 -07002081 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08002082
Ed Tanous8d69c662023-06-21 10:29:06 -07002083 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08002084 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002085 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06002086 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08002087 return;
2088 }
2089
George Liu9ae226f2023-06-21 17:56:46 +08002090 sdbusplus::asio::setProperty(
2091 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
George Liuc6a620f2020-04-10 17:18:11 +08002092 "/xyz/openbmc_project/control/host0/power_restore_policy",
George Liuc6a620f2020-04-10 17:18:11 +08002093 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
George Liu9ae226f2023-06-21 17:56:46 +08002094 powerRestorePolicy, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -05002095 if (ec)
2096 {
2097 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
2098 messages::internalError(asyncResp->res);
2099 return;
2100 }
2101 });
George Liuc6a620f2020-04-10 17:18:11 +08002102}
2103
AppaRao Pulia6349912019-10-18 17:16:08 +05302104#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2105/**
2106 * @brief Retrieves provisioning status
2107 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002108 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05302109 *
2110 * @return None.
2111 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002112inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05302113{
Ed Tanous62598e32023-07-17 17:06:25 -07002114 BMCWEB_LOG_DEBUG("Get OEM information.");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002115 sdbusplus::asio::getAllProperties(
2116 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
2117 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07002118 [asyncResp](const boost::system::error_code& ec,
2119 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002120 nlohmann::json& oemPFR =
Ed Tanousac106bf2023-06-07 09:24:59 -07002121 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
2122 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07002123 "#OemComputerSystem.OpenBmc";
2124 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07002125
Ed Tanous002d39b2022-05-31 08:59:27 -07002126 if (ec)
2127 {
Ed Tanous62598e32023-07-17 17:06:25 -07002128 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002129 // not an error, don't have to have the interface
2130 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2131 return;
2132 }
2133
2134 const bool* provState = nullptr;
2135 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002136
2137 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08002138 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
2139 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002140
2141 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002142 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002143 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002144 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002145 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302146
Ed Tanous002d39b2022-05-31 08:59:27 -07002147 if ((provState == nullptr) || (lockState == nullptr))
2148 {
Ed Tanous62598e32023-07-17 17:06:25 -07002149 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
Ed Tanousac106bf2023-06-07 09:24:59 -07002150 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002151 return;
2152 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302153
Ed Tanous002d39b2022-05-31 08:59:27 -07002154 if (*provState == true)
2155 {
2156 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05302157 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002158 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302159 }
2160 else
2161 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002162 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302163 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002164 }
2165 else
2166 {
2167 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2168 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002169 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302170}
2171#endif
2172
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302173/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002174 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002175 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002176 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002177 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002178 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002179 */
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002180inline computer_system::PowerMode
2181 translatePowerModeString(const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002182{
Chris Cainb6655102024-02-01 14:35:33 -06002183 using PowerMode = computer_system::PowerMode;
2184
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002185 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002186 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002187 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002188 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002189 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002190 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002191 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002192 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002193 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002194 if (modeString ==
2195 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002196 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002197 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002198 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002199 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002200 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2201 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002202 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002203 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002204 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002205 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2206 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002207 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002208 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002209 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002210 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2211 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002212 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002213 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002214 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002215 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002216 return PowerMode::OEM;
2217 }
2218 // Any other values would be invalid
2219 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2220 return PowerMode::Invalid;
2221}
2222
2223inline void
2224 afterGetPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2225 const boost::system::error_code& ec,
2226 const dbus::utility::DBusPropertiesMap& properties)
2227{
2228 if (ec)
2229 {
2230 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2231 messages::internalError(asyncResp->res);
2232 return;
2233 }
2234
2235 std::string powerMode;
2236 const std::vector<std::string>* allowedModes = nullptr;
2237 const bool success = sdbusplus::unpackPropertiesNoThrow(
2238 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2239 "AllowedPowerModes", allowedModes);
2240
2241 if (!success)
2242 {
2243 messages::internalError(asyncResp->res);
2244 return;
2245 }
2246
2247 nlohmann::json::array_t modeList;
2248 if (allowedModes == nullptr)
2249 {
2250 modeList.emplace_back("Static");
2251 modeList.emplace_back("MaximumPerformance");
2252 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002253 }
2254 else
2255 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002256 for (const auto& aMode : *allowedModes)
2257 {
2258 computer_system::PowerMode modeValue =
2259 translatePowerModeString(aMode);
2260 if (modeValue == computer_system::PowerMode::Invalid)
2261 {
2262 messages::internalError(asyncResp->res);
2263 continue;
2264 }
2265 modeList.emplace_back(modeValue);
2266 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002267 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002268 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002269
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002270 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2271 const computer_system::PowerMode modeValue =
2272 translatePowerModeString(powerMode);
2273 if (modeValue == computer_system::PowerMode::Invalid)
2274 {
2275 messages::internalError(asyncResp->res);
2276 return;
2277 }
2278 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2279}
Chris Cain3a2d04242021-05-28 16:57:10 -05002280/**
2281 * @brief Retrieves system power mode
2282 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002283 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002284 *
2285 * @return None.
2286 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002287inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002288{
Ed Tanous62598e32023-07-17 17:06:25 -07002289 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002290
2291 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002292 constexpr std::array<std::string_view, 1> interfaces = {
2293 "xyz.openbmc_project.Control.Power.Mode"};
2294 dbus::utility::getSubTree(
2295 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002296 [asyncResp](const boost::system::error_code& ec,
2297 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002298 if (ec)
2299 {
Ed Tanous62598e32023-07-17 17:06:25 -07002300 BMCWEB_LOG_DEBUG("DBUS response error on Power.Mode GetSubTree {}",
2301 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002302 // This is an optional D-Bus object so just return if
2303 // error occurs
2304 return;
2305 }
2306 if (subtree.empty())
2307 {
2308 // As noted above, this is an optional interface so just return
2309 // if there is no instance found
2310 return;
2311 }
2312 if (subtree.size() > 1)
2313 {
2314 // More then one PowerMode object is not supported and is an
2315 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002316 BMCWEB_LOG_DEBUG(
2317 "Found more than 1 system D-Bus Power.Mode objects: {}",
2318 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002319 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002320 return;
2321 }
2322 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2323 {
Ed Tanous62598e32023-07-17 17:06:25 -07002324 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002325 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002326 return;
2327 }
2328 const std::string& path = subtree[0].first;
2329 const std::string& service = subtree[0].second.begin()->first;
2330 if (service.empty())
2331 {
Ed Tanous62598e32023-07-17 17:06:25 -07002332 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002333 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002334 return;
2335 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002336
2337 // Valid Power Mode object found, now read the mode properties
2338 sdbusplus::asio::getAllProperties(
Ed Tanous002d39b2022-05-31 08:59:27 -07002339 *crow::connections::systemBus, service, path,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002340 "xyz.openbmc_project.Control.Power.Mode",
Ed Tanousac106bf2023-06-07 09:24:59 -07002341 [asyncResp](const boost::system::error_code& ec2,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002342 const dbus::utility::DBusPropertiesMap& properties) {
2343 afterGetPowerMode(asyncResp, ec2, properties);
George Liue99073f2022-12-09 11:06:16 +08002344 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002345 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002346}
2347
2348/**
2349 * @brief Validate the specified mode is valid and return the PowerMode
2350 * name associated with that string
2351 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002352 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002353 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002354 *
2355 * @return PowerMode value or empty string if mode is not valid
2356 */
2357inline std::string
Ed Tanousac106bf2023-06-07 09:24:59 -07002358 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cainb6655102024-02-01 14:35:33 -06002359 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002360{
Chris Cainb6655102024-02-01 14:35:33 -06002361 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002362 std::string mode;
2363
Chris Cainb6655102024-02-01 14:35:33 -06002364 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002365 {
2366 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2367 }
Chris Cainb6655102024-02-01 14:35:33 -06002368 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002369 {
George Liu0fda0f12021-11-16 10:06:17 +08002370 mode =
2371 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002372 }
Chris Cainb6655102024-02-01 14:35:33 -06002373 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002374 {
2375 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2376 }
Chris Cainb6655102024-02-01 14:35:33 -06002377 else if (modeValue == PowerMode::BalancedPerformance)
2378 {
2379 mode =
2380 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2381 }
2382 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2383 {
2384 mode =
2385 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2386 }
2387 else if (modeValue == PowerMode::EfficiencyFavorPower)
2388 {
2389 mode =
2390 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2391 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002392 else
2393 {
Chris Cainb6655102024-02-01 14:35:33 -06002394 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002395 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002396 }
2397 return mode;
2398}
2399
2400/**
2401 * @brief Sets system power mode.
2402 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002403 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002404 * @param[in] pmode System power mode from request.
2405 *
2406 * @return None.
2407 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002408inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002409 const std::string& pmode)
2410{
Ed Tanous62598e32023-07-17 17:06:25 -07002411 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002412
Ed Tanousac106bf2023-06-07 09:24:59 -07002413 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002414 if (powerMode.empty())
2415 {
2416 return;
2417 }
2418
2419 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002420 constexpr std::array<std::string_view, 1> interfaces = {
2421 "xyz.openbmc_project.Control.Power.Mode"};
2422 dbus::utility::getSubTree(
2423 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002424 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002425 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002426 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002427 if (ec)
2428 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002429 BMCWEB_LOG_ERROR("DBUS response error on Power.Mode GetSubTree {}",
Ed Tanous62598e32023-07-17 17:06:25 -07002430 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002431 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002432 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002433 return;
2434 }
2435 if (subtree.empty())
2436 {
2437 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002438 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002439 "PowerMode");
2440 return;
2441 }
2442 if (subtree.size() > 1)
2443 {
2444 // More then one PowerMode object is not supported and is an
2445 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002446 BMCWEB_LOG_DEBUG(
2447 "Found more than 1 system D-Bus Power.Mode objects: {}",
2448 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002449 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002450 return;
2451 }
2452 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2453 {
Ed Tanous62598e32023-07-17 17:06:25 -07002454 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002455 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002456 return;
2457 }
2458 const std::string& path = subtree[0].first;
2459 const std::string& service = subtree[0].second.begin()->first;
2460 if (service.empty())
2461 {
Ed Tanous62598e32023-07-17 17:06:25 -07002462 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002463 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002464 return;
2465 }
2466
Ed Tanous62598e32023-07-17 17:06:25 -07002467 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002468
2469 // Set the Power Mode property
George Liu9ae226f2023-06-21 17:56:46 +08002470 sdbusplus::asio::setProperty(
2471 *crow::connections::systemBus, service, path,
2472 "xyz.openbmc_project.Control.Power.Mode", "PowerMode", powerMode,
Ed Tanousac106bf2023-06-07 09:24:59 -07002473 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002474 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002475 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002476 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002477 messages::internalError(asyncResp->res);
Chris Cain3a2d04242021-05-28 16:57:10 -05002478 return;
2479 }
George Liue99073f2022-12-09 11:06:16 +08002480 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002481 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002482}
2483
2484/**
Yong Li51709ff2019-09-30 14:13:04 +08002485 * @brief Translates watchdog timeout action DBUS property value to redfish.
2486 *
2487 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2488 *
2489 * @return Returns as a string, the timeout action in Redfish terms. If
2490 * translation cannot be done, returns an empty string.
2491 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002492inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002493{
2494 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2495 {
2496 return "None";
2497 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002498 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002499 {
2500 return "ResetSystem";
2501 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002502 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002503 {
2504 return "PowerDown";
2505 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002506 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002507 {
2508 return "PowerCycle";
2509 }
2510
2511 return "";
2512}
2513
2514/**
Yong Lic45f0082019-10-10 14:19:01 +08002515 *@brief Translates timeout action from Redfish to DBUS property value.
2516 *
2517 *@param[in] rfAction The timeout action in Redfish.
2518 *
2519 *@return Returns as a string, the time_out action as expected by DBUS.
2520 *If translation cannot be done, returns an empty string.
2521 */
2522
Ed Tanous23a21a12020-07-25 04:45:05 +00002523inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002524{
2525 if (rfAction == "None")
2526 {
2527 return "xyz.openbmc_project.State.Watchdog.Action.None";
2528 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002529 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002530 {
2531 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2532 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002533 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002534 {
2535 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2536 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002537 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002538 {
2539 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2540 }
2541
2542 return "";
2543}
2544
2545/**
Yong Li51709ff2019-09-30 14:13:04 +08002546 * @brief Retrieves host watchdog timer properties over DBUS
2547 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002548 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002549 *
2550 * @return None.
2551 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002552inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002553 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002554{
Ed Tanous62598e32023-07-17 17:06:25 -07002555 BMCWEB_LOG_DEBUG("Get host watchodg");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002556 sdbusplus::asio::getAllProperties(
2557 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2558 "/xyz/openbmc_project/watchdog/host0",
2559 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002560 [asyncResp](const boost::system::error_code& ec,
2561 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002562 if (ec)
2563 {
2564 // watchdog service is stopped
Ed Tanous62598e32023-07-17 17:06:25 -07002565 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002566 return;
2567 }
2568
Ed Tanous62598e32023-07-17 17:06:25 -07002569 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002570
2571 nlohmann::json& hostWatchdogTimer =
Ed Tanousac106bf2023-06-07 09:24:59 -07002572 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002573
2574 // watchdog service is running/enabled
2575 hostWatchdogTimer["Status"]["State"] = "Enabled";
2576
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002577 const bool* enabled = nullptr;
2578 const std::string* expireAction = nullptr;
2579
2580 const bool success = sdbusplus::unpackPropertiesNoThrow(
2581 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2582 "ExpireAction", expireAction);
2583
2584 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002585 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002586 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002587 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002588 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002589
2590 if (enabled != nullptr)
2591 {
2592 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2593 }
2594
2595 if (expireAction != nullptr)
2596 {
2597 std::string action = dbusToRfWatchdogAction(*expireAction);
2598 if (action.empty())
2599 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002600 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002601 return;
2602 }
2603 hostWatchdogTimer["TimeoutAction"] = action;
2604 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002605 });
Yong Li51709ff2019-09-30 14:13:04 +08002606}
2607
2608/**
Yong Lic45f0082019-10-10 14:19:01 +08002609 * @brief Sets Host WatchDog Timer properties.
2610 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002611 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002612 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2613 * RF request.
2614 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2615 *
2616 * @return None.
2617 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002618inline void
2619 setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2620 const std::optional<bool> wdtEnable,
2621 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002622{
Ed Tanous62598e32023-07-17 17:06:25 -07002623 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002624
2625 if (wdtTimeOutAction)
2626 {
2627 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2628 // check if TimeOut Action is Valid
2629 if (wdtTimeOutActStr.empty())
2630 {
Ed Tanous62598e32023-07-17 17:06:25 -07002631 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2632 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002633 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002634 "TimeoutAction");
2635 return;
2636 }
2637
George Liu9ae226f2023-06-21 17:56:46 +08002638 sdbusplus::asio::setProperty(
2639 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
Yong Lic45f0082019-10-10 14:19:01 +08002640 "/xyz/openbmc_project/watchdog/host0",
Yong Lic45f0082019-10-10 14:19:01 +08002641 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
George Liu9ae226f2023-06-21 17:56:46 +08002642 wdtTimeOutActStr, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -05002643 if (ec)
2644 {
2645 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
2646 messages::internalError(asyncResp->res);
2647 return;
2648 }
2649 });
Yong Lic45f0082019-10-10 14:19:01 +08002650 }
2651
2652 if (wdtEnable)
2653 {
George Liu9ae226f2023-06-21 17:56:46 +08002654 sdbusplus::asio::setProperty(
2655 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2656 "/xyz/openbmc_project/watchdog/host0",
2657 "xyz.openbmc_project.State.Watchdog", "Enabled", *wdtEnable,
Ed Tanousac106bf2023-06-07 09:24:59 -07002658 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002659 if (ec)
2660 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002661 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002662 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002663 return;
2664 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002665 });
Yong Lic45f0082019-10-10 14:19:01 +08002666 }
2667}
2668
Chris Cain37bbf982021-09-20 10:53:09 -05002669/**
2670 * @brief Parse the Idle Power Saver properties into json
2671 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002672 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002673 * @param[in] properties IPS property data from DBus.
2674 *
2675 * @return true if successful
2676 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002677inline bool
Ed Tanousac106bf2023-06-07 09:24:59 -07002678 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002679 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002680{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002681 const bool* enabled = nullptr;
2682 const uint8_t* enterUtilizationPercent = nullptr;
2683 const uint64_t* enterDwellTime = nullptr;
2684 const uint8_t* exitUtilizationPercent = nullptr;
2685 const uint64_t* exitDwellTime = nullptr;
2686
2687 const bool success = sdbusplus::unpackPropertiesNoThrow(
2688 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002689 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2690 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2691 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002692
2693 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002694 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002695 return false;
2696 }
2697
2698 if (enabled != nullptr)
2699 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002700 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002701 }
2702
2703 if (enterUtilizationPercent != nullptr)
2704 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002705 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002706 *enterUtilizationPercent;
2707 }
2708
2709 if (enterDwellTime != nullptr)
2710 {
2711 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002712 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002713 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2714 .count();
2715 }
2716
2717 if (exitUtilizationPercent != nullptr)
2718 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002719 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002720 *exitUtilizationPercent;
2721 }
2722
2723 if (exitDwellTime != nullptr)
2724 {
2725 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002726 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002727 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2728 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002729 }
2730
2731 return true;
2732}
2733
2734/**
2735 * @brief Retrieves host watchdog timer properties over DBUS
2736 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002737 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002738 *
2739 * @return None.
2740 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002741inline void
2742 getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002743{
Ed Tanous62598e32023-07-17 17:06:25 -07002744 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002745
2746 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002747 constexpr std::array<std::string_view, 1> interfaces = {
2748 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2749 dbus::utility::getSubTree(
2750 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002751 [asyncResp](const boost::system::error_code& ec,
2752 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002753 if (ec)
2754 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002755 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002756 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2757 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002758 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002759 return;
2760 }
2761 if (subtree.empty())
2762 {
2763 // This is an optional interface so just return
2764 // if there is no instance found
Ed Tanous62598e32023-07-17 17:06:25 -07002765 BMCWEB_LOG_DEBUG("No instances found");
Ed Tanous002d39b2022-05-31 08:59:27 -07002766 return;
2767 }
2768 if (subtree.size() > 1)
2769 {
2770 // More then one PowerIdlePowerSaver object is not supported and
2771 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002772 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2773 "Power.IdlePowerSaver objects: {}",
2774 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002775 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002776 return;
2777 }
2778 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2779 {
Ed Tanous62598e32023-07-17 17:06:25 -07002780 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002781 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002782 return;
2783 }
2784 const std::string& path = subtree[0].first;
2785 const std::string& service = subtree[0].second.begin()->first;
2786 if (service.empty())
2787 {
Ed Tanous62598e32023-07-17 17:06:25 -07002788 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002789 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002790 return;
2791 }
2792
2793 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002794 sdbusplus::asio::getAllProperties(
2795 *crow::connections::systemBus, service, path,
2796 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanousac106bf2023-06-07 09:24:59 -07002797 [asyncResp](const boost::system::error_code& ec2,
2798 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002799 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002800 {
Ed Tanous62598e32023-07-17 17:06:25 -07002801 BMCWEB_LOG_ERROR(
2802 "DBUS response error on IdlePowerSaver GetAll: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002803 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002804 return;
2805 }
2806
Ed Tanousac106bf2023-06-07 09:24:59 -07002807 if (!parseIpsProperties(asyncResp, properties))
Ed Tanous002d39b2022-05-31 08:59:27 -07002808 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002809 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002810 return;
2811 }
George Liue99073f2022-12-09 11:06:16 +08002812 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002813 });
Chris Cain37bbf982021-09-20 10:53:09 -05002814
Ed Tanous62598e32023-07-17 17:06:25 -07002815 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002816}
2817
2818/**
2819 * @brief Sets Idle Power Saver properties.
2820 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002821 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002822 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2823 * RF request.
2824 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2825 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2826 * before entering idle state.
2827 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2828 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2829 * before exiting idle state
2830 *
2831 * @return None.
2832 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002833inline void
2834 setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2835 const std::optional<bool> ipsEnable,
2836 const std::optional<uint8_t> ipsEnterUtil,
2837 const std::optional<uint64_t> ipsEnterTime,
2838 const std::optional<uint8_t> ipsExitUtil,
2839 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002840{
Ed Tanous62598e32023-07-17 17:06:25 -07002841 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002842
2843 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002844 constexpr std::array<std::string_view, 1> interfaces = {
2845 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2846 dbus::utility::getSubTree(
2847 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002848 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002849 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002850 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002851 if (ec)
2852 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002853 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002854 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2855 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002856 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002857 return;
2858 }
2859 if (subtree.empty())
2860 {
2861 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002862 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002863 "IdlePowerSaver");
2864 return;
2865 }
2866 if (subtree.size() > 1)
2867 {
2868 // More then one PowerIdlePowerSaver object is not supported and
2869 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002870 BMCWEB_LOG_DEBUG(
2871 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2872 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002873 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002874 return;
2875 }
2876 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2877 {
Ed Tanous62598e32023-07-17 17:06:25 -07002878 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002879 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002880 return;
2881 }
2882 const std::string& path = subtree[0].first;
2883 const std::string& service = subtree[0].second.begin()->first;
2884 if (service.empty())
2885 {
Ed Tanous62598e32023-07-17 17:06:25 -07002886 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002887 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002888 return;
2889 }
Chris Cain37bbf982021-09-20 10:53:09 -05002890
Ed Tanous002d39b2022-05-31 08:59:27 -07002891 // Valid Power IdlePowerSaver object found, now set any values that
2892 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002893
Ed Tanous002d39b2022-05-31 08:59:27 -07002894 if (ipsEnable)
2895 {
George Liu9ae226f2023-06-21 17:56:46 +08002896 sdbusplus::asio::setProperty(
2897 *crow::connections::systemBus, service, path,
Ed Tanous002d39b2022-05-31 08:59:27 -07002898 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
George Liu9ae226f2023-06-21 17:56:46 +08002899 *ipsEnable, [asyncResp](const boost::system::error_code& ec2) {
Patrick Williams5a39f772023-10-20 11:20:21 -05002900 if (ec2)
2901 {
2902 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
2903 messages::internalError(asyncResp->res);
2904 return;
2905 }
2906 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002907 }
2908 if (ipsEnterUtil)
2909 {
George Liu9ae226f2023-06-21 17:56:46 +08002910 sdbusplus::asio::setProperty(
2911 *crow::connections::systemBus, service, path,
2912 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2913 "EnterUtilizationPercent", *ipsEnterUtil,
Ed Tanousac106bf2023-06-07 09:24:59 -07002914 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002915 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002916 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002917 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002918 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002919 return;
2920 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002921 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002922 }
2923 if (ipsEnterTime)
2924 {
2925 // Convert from seconds into milliseconds for DBus
2926 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
George Liu9ae226f2023-06-21 17:56:46 +08002927 sdbusplus::asio::setProperty(
2928 *crow::connections::systemBus, service, path,
2929 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2930 "EnterDwellTime", timeMilliseconds,
Ed Tanousac106bf2023-06-07 09:24:59 -07002931 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002932 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002933 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002934 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002935 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002936 return;
2937 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002938 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002939 }
2940 if (ipsExitUtil)
2941 {
George Liu9ae226f2023-06-21 17:56:46 +08002942 sdbusplus::asio::setProperty(
2943 *crow::connections::systemBus, service, path,
2944 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2945 "ExitUtilizationPercent", *ipsExitUtil,
Ed Tanousac106bf2023-06-07 09:24:59 -07002946 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002947 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002948 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002949 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002950 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002951 return;
2952 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002953 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002954 }
2955 if (ipsExitTime)
2956 {
2957 // Convert from seconds into milliseconds for DBus
2958 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
George Liu9ae226f2023-06-21 17:56:46 +08002959 sdbusplus::asio::setProperty(
2960 *crow::connections::systemBus, service, path,
2961 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2962 "ExitDwellTime", timeMilliseconds,
Ed Tanousac106bf2023-06-07 09:24:59 -07002963 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002964 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002965 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002966 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002967 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002968 return;
2969 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002970 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002971 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002972 });
Chris Cain37bbf982021-09-20 10:53:09 -05002973
Ed Tanous62598e32023-07-17 17:06:25 -07002974 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002975}
2976
Ed Tanousc1e219d2023-06-07 10:34:33 -07002977inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002978 crow::App& app, const crow::Request& req,
2979 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2980{
2981 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2982 {
2983 return;
2984 }
2985 asyncResp->res.addHeader(
2986 boost::beast::http::field::link,
2987 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2988}
2989
Ed Tanousc1e219d2023-06-07 10:34:33 -07002990inline void handleComputerSystemCollectionGet(
2991 crow::App& app, const crow::Request& req,
2992 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2993{
2994 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2995 {
2996 return;
2997 }
2998
2999 asyncResp->res.addHeader(
3000 boost::beast::http::field::link,
3001 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
3002 asyncResp->res.jsonValue["@odata.type"] =
3003 "#ComputerSystemCollection.ComputerSystemCollection";
3004 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
3005 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
3006
3007 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
3008 ifaceArray = nlohmann::json::array();
3009 if constexpr (bmcwebEnableMultiHost)
3010 {
3011 asyncResp->res.jsonValue["Members@odata.count"] = 0;
3012 // Option currently returns no systems. TBD
3013 return;
3014 }
3015 asyncResp->res.jsonValue["Members@odata.count"] = 1;
3016 nlohmann::json::object_t system;
3017 system["@odata.id"] = "/redfish/v1/Systems/system";
3018 ifaceArray.emplace_back(std::move(system));
3019 sdbusplus::asio::getProperty<std::string>(
3020 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
3021 "/xyz/openbmc_project/network/hypervisor",
3022 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
3023 [asyncResp](const boost::system::error_code& ec2,
3024 const std::string& /*hostName*/) {
3025 if (ec2)
3026 {
3027 return;
3028 }
3029 auto val = asyncResp->res.jsonValue.find("Members@odata.count");
3030 if (val == asyncResp->res.jsonValue.end())
3031 {
Ed Tanous62598e32023-07-17 17:06:25 -07003032 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07003033 return;
3034 }
3035 uint64_t* count = val->get_ptr<uint64_t*>();
3036 if (count == nullptr)
3037 {
Ed Tanous62598e32023-07-17 17:06:25 -07003038 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07003039 return;
3040 }
3041 *count = *count + 1;
Ed Tanous62598e32023-07-17 17:06:25 -07003042 BMCWEB_LOG_DEBUG("Hypervisor is available");
Ed Tanousc1e219d2023-06-07 10:34:33 -07003043 nlohmann::json& ifaceArray2 = asyncResp->res.jsonValue["Members"];
3044 nlohmann::json::object_t hypervisor;
3045 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
3046 ifaceArray2.emplace_back(std::move(hypervisor));
Patrick Williams5a39f772023-10-20 11:20:21 -05003047 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003048}
3049
Yong Lic45f0082019-10-10 14:19:01 +08003050/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003051 * Function transceives data with dbus directly.
3052 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07003053inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003054{
Patrick Williams89492a12023-05-10 07:51:34 -05003055 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
3056 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
3057 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003058 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05003059 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003060
3061 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08003062 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07003063 if (ec)
3064 {
Ed Tanous62598e32023-07-17 17:06:25 -07003065 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07003066 messages::internalError(asyncResp->res);
3067 return;
3068 }
3069 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05003070 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003071 serviceName, objectPath, interfaceName, method);
3072}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003073
3074/**
Andrew Geisslerfc903b32023-05-31 14:15:42 -04003075 * Handle error responses from d-bus for system power requests
3076 */
3077inline void handleSystemActionResetError(const boost::system::error_code& ec,
3078 const sdbusplus::message_t& eMsg,
3079 std::string_view resetType,
3080 crow::Response& res)
3081{
3082 if (ec.value() == boost::asio::error::invalid_argument)
3083 {
3084 messages::actionParameterNotSupported(res, resetType, "Reset");
3085 return;
3086 }
3087
3088 if (eMsg.get_error() == nullptr)
3089 {
Ed Tanous62598e32023-07-17 17:06:25 -07003090 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
Andrew Geisslerfc903b32023-05-31 14:15:42 -04003091 messages::internalError(res);
3092 return;
3093 }
3094 std::string_view errorMessage = eMsg.get_error()->name;
3095
3096 // If operation failed due to BMC not being in Ready state, tell
3097 // user to retry in a bit
3098 if ((errorMessage ==
3099 std::string_view(
3100 "xyz.openbmc_project.State.Chassis.Error.BMCNotReady")) ||
3101 (errorMessage ==
3102 std::string_view("xyz.openbmc_project.State.Host.Error.BMCNotReady")))
3103 {
Ed Tanous62598e32023-07-17 17:06:25 -07003104 BMCWEB_LOG_DEBUG("BMC not ready, operation not allowed right now");
Andrew Geisslerfc903b32023-05-31 14:15:42 -04003105 messages::serviceTemporarilyUnavailable(res, "10");
3106 return;
3107 }
3108
Ed Tanous62598e32023-07-17 17:06:25 -07003109 BMCWEB_LOG_ERROR("System Action Reset transition fail {} sdbusplus:{}", ec,
3110 errorMessage);
Andrew Geisslerfc903b32023-05-31 14:15:42 -04003111 messages::internalError(res);
3112}
3113
Ed Tanousc1e219d2023-06-07 10:34:33 -07003114inline void handleComputerSystemResetActionPost(
3115 crow::App& app, const crow::Request& req,
3116 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3117 const std::string& systemName)
3118{
3119 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3120 {
3121 return;
3122 }
3123 if (systemName != "system")
3124 {
3125 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3126 systemName);
3127 return;
3128 }
3129 if constexpr (bmcwebEnableMultiHost)
3130 {
3131 // Option currently returns no systems. TBD
3132 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3133 systemName);
3134 return;
3135 }
3136 std::string resetType;
3137 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
3138 {
3139 return;
3140 }
3141
3142 // Get the command and host vs. chassis
3143 std::string command;
3144 bool hostCommand = true;
3145 if ((resetType == "On") || (resetType == "ForceOn"))
3146 {
3147 command = "xyz.openbmc_project.State.Host.Transition.On";
3148 hostCommand = true;
3149 }
3150 else if (resetType == "ForceOff")
3151 {
3152 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
3153 hostCommand = false;
3154 }
3155 else if (resetType == "ForceRestart")
3156 {
3157 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
3158 hostCommand = true;
3159 }
3160 else if (resetType == "GracefulShutdown")
3161 {
3162 command = "xyz.openbmc_project.State.Host.Transition.Off";
3163 hostCommand = true;
3164 }
3165 else if (resetType == "GracefulRestart")
3166 {
3167 command =
3168 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
3169 hostCommand = true;
3170 }
3171 else if (resetType == "PowerCycle")
3172 {
3173 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
3174 hostCommand = true;
3175 }
3176 else if (resetType == "Nmi")
3177 {
3178 doNMI(asyncResp);
3179 return;
3180 }
3181 else
3182 {
3183 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
3184 return;
3185 }
3186
3187 if (hostCommand)
3188 {
George Liu9ae226f2023-06-21 17:56:46 +08003189 sdbusplus::asio::setProperty(
3190 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
3191 "/xyz/openbmc_project/state/host0",
3192 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
3193 command,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003194 [asyncResp, resetType](const boost::system::error_code& ec,
3195 sdbusplus::message_t& sdbusErrMsg) {
3196 if (ec)
3197 {
3198 handleSystemActionResetError(ec, sdbusErrMsg, resetType,
3199 asyncResp->res);
3200
3201 return;
3202 }
3203 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05003204 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003205 }
3206 else
3207 {
George Liu9ae226f2023-06-21 17:56:46 +08003208 sdbusplus::asio::setProperty(
3209 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
3210 "/xyz/openbmc_project/state/chassis0",
3211 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
3212 command,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003213 [asyncResp, resetType](const boost::system::error_code& ec,
3214 sdbusplus::message_t& sdbusErrMsg) {
3215 if (ec)
3216 {
3217 handleSystemActionResetError(ec, sdbusErrMsg, resetType,
3218 asyncResp->res);
3219 return;
3220 }
3221 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05003222 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003223 }
3224}
3225
Ed Tanousc1e219d2023-06-07 10:34:33 -07003226inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003227 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3229 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003230{
3231 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3232 {
3233 return;
3234 }
3235
3236 asyncResp->res.addHeader(
3237 boost::beast::http::field::link,
3238 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3239}
3240
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003241inline void afterPortRequest(
3242 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3243 const boost::system::error_code& ec,
3244 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3245{
3246 if (ec)
3247 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003248 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003249 messages::internalError(asyncResp->res);
3250 return;
3251 }
3252 for (const auto& data : socketData)
3253 {
3254 const std::string& socketPath = get<0>(data);
3255 const std::string& protocolName = get<1>(data);
3256 bool isProtocolEnabled = get<2>(data);
3257 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3258 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3259 // need to retrieve port number for
3260 // obmc-console-ssh service
3261 if (protocolName == "SSH")
3262 {
3263 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003264 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003265 int portNumber) {
3266 if (ec1)
3267 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003268 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003269 messages::internalError(asyncResp->res);
3270 return;
3271 }
3272 nlohmann::json& dataJson1 =
3273 asyncResp->res.jsonValue["SerialConsole"];
3274 dataJson1[protocolName]["Port"] = portNumber;
3275 });
3276 }
3277 }
3278}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003279
3280inline void
3281 handleComputerSystemGet(crow::App& app, const crow::Request& req,
3282 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3283 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003284{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003285 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3286 {
3287 return;
3288 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003289
Ed Tanousc1e219d2023-06-07 10:34:33 -07003290 if constexpr (bmcwebEnableMultiHost)
3291 {
3292 // Option currently returns no systems. TBD
3293 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3294 systemName);
3295 return;
3296 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003297
Ed Tanousc1e219d2023-06-07 10:34:33 -07003298 if (systemName == "hypervisor")
3299 {
3300 handleHypervisorSystemGet(asyncResp);
3301 return;
3302 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003303
Ed Tanousc1e219d2023-06-07 10:34:33 -07003304 if (systemName != "system")
3305 {
3306 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3307 systemName);
3308 return;
3309 }
3310 asyncResp->res.addHeader(
3311 boost::beast::http::field::link,
3312 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3313 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003314 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanousc1e219d2023-06-07 10:34:33 -07003315 asyncResp->res.jsonValue["Name"] = "system";
3316 asyncResp->res.jsonValue["Id"] = "system";
3317 asyncResp->res.jsonValue["SystemType"] = "Physical";
3318 asyncResp->res.jsonValue["Description"] = "Computer System";
3319 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3320 if constexpr (bmcwebEnableProcMemStatus)
3321 {
3322 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3323 "Disabled";
3324 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3325 "Disabled";
3326 }
3327 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003328 double(0);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003329 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003330
Ed Tanousc1e219d2023-06-07 10:34:33 -07003331 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3332 "/redfish/v1/Systems/system/Processors";
3333 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3334 "/redfish/v1/Systems/system/Memory";
3335 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3336 "/redfish/v1/Systems/system/Storage";
3337 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3338 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003339
Ed Tanousc1e219d2023-06-07 10:34:33 -07003340 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3341 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3342 asyncResp->res
3343 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
3344 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003345
Ed Tanousc1e219d2023-06-07 10:34:33 -07003346 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3347 "/redfish/v1/Systems/system/LogServices";
3348 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3349 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003350
Ed Tanousc1e219d2023-06-07 10:34:33 -07003351 nlohmann::json::array_t managedBy;
3352 nlohmann::json& manager = managedBy.emplace_back();
3353 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3354 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3355 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3356 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003357
Ed Tanousc1e219d2023-06-07 10:34:33 -07003358 // Fill in SerialConsole info
3359 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3360 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003361
Ed Tanousc1e219d2023-06-07 10:34:33 -07003362 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3363 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3364 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3365 "Press ~. to exit console";
3366 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3367 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003368
3369#ifdef BMCWEB_ENABLE_KVM
Ed Tanousc1e219d2023-06-07 10:34:33 -07003370 // Fill in GraphicalConsole info
3371 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3372 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4;
3373 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3374 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003375
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003376#endif // BMCWEB_ENABLE_KVM
James Feistb49ac872019-05-21 15:12:01 -07003377
Ed Tanousc1e219d2023-06-07 10:34:33 -07003378 auto health = std::make_shared<HealthPopulate>(asyncResp);
3379 if constexpr (bmcwebEnableHealthPopulate)
3380 {
3381 constexpr std::array<std::string_view, 4> inventoryForSystems{
3382 "xyz.openbmc_project.Inventory.Item.Dimm",
3383 "xyz.openbmc_project.Inventory.Item.Cpu",
3384 "xyz.openbmc_project.Inventory.Item.Drive",
3385 "xyz.openbmc_project.Inventory.Item.StorageController"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003386
Ed Tanousc1e219d2023-06-07 10:34:33 -07003387 dbus::utility::getSubTreePaths(
3388 "/", 0, inventoryForSystems,
3389 [health](const boost::system::error_code& ec,
3390 const std::vector<std::string>& resp) {
3391 if (ec)
3392 {
3393 // no inventory
3394 return;
3395 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003396
Ed Tanousc1e219d2023-06-07 10:34:33 -07003397 health->inventory = resp;
Patrick Williams5a39f772023-10-20 11:20:21 -05003398 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003399 health->populate();
3400 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003401
Ed Tanousc1e219d2023-06-07 10:34:33 -07003402 getMainChassisId(asyncResp,
3403 [](const std::string& chassisId,
3404 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3405 nlohmann::json::array_t chassisArray;
3406 nlohmann::json& chassis = chassisArray.emplace_back();
3407 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3408 chassisId);
3409 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3410 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003411
George Liu59a17e42022-10-08 09:27:47 +08003412 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003413 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3414 getIndicatorLedState(asyncResp);
3415 getComputerSystem(asyncResp, health);
3416 getHostState(asyncResp);
3417 getBootProperties(asyncResp);
3418 getBootProgress(asyncResp);
3419 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003420 pcie_util::getPCIeDeviceList(asyncResp,
3421 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003422 getHostWatchdogTimer(asyncResp);
3423 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003424 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003425 getAutomaticRetryPolicy(asyncResp);
3426 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003427#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanousc1e219d2023-06-07 10:34:33 -07003428 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003429#endif
Ed Tanousc1e219d2023-06-07 10:34:33 -07003430 getTrustedModuleRequiredToBoot(asyncResp);
3431 getPowerMode(asyncResp);
3432 getIdlePowerSaver(asyncResp);
3433}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003434
Ed Tanousc1e219d2023-06-07 10:34:33 -07003435inline void handleComputerSystemPatch(
3436 crow::App& app, const crow::Request& req,
3437 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3438 const std::string& systemName)
3439{
3440 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3441 {
3442 return;
3443 }
3444 if constexpr (bmcwebEnableMultiHost)
3445 {
3446 // Option currently returns no systems. TBD
3447 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3448 systemName);
3449 return;
3450 }
3451 if (systemName != "system")
3452 {
3453 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3454 systemName);
3455 return;
3456 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003457
Ed Tanousc1e219d2023-06-07 10:34:33 -07003458 asyncResp->res.addHeader(
3459 boost::beast::http::field::link,
3460 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003461
Ed Tanousc1e219d2023-06-07 10:34:33 -07003462 std::optional<bool> locationIndicatorActive;
3463 std::optional<std::string> indicatorLed;
3464 std::optional<std::string> assetTag;
3465 std::optional<std::string> powerRestorePolicy;
3466 std::optional<std::string> powerMode;
3467 std::optional<bool> wdtEnable;
3468 std::optional<std::string> wdtTimeOutAction;
3469 std::optional<std::string> bootSource;
3470 std::optional<std::string> bootType;
3471 std::optional<std::string> bootEnable;
3472 std::optional<std::string> bootAutomaticRetry;
3473 std::optional<uint32_t> bootAutomaticRetryAttempts;
3474 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003475 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003476 std::optional<bool> ipsEnable;
3477 std::optional<uint8_t> ipsEnterUtil;
3478 std::optional<uint64_t> ipsEnterTime;
3479 std::optional<uint8_t> ipsExitUtil;
3480 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003481
Ed Tanousc1e219d2023-06-07 10:34:33 -07003482 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003483 if (!json_util::readJsonPatch(
3484 req, asyncResp->res,
3485 "IndicatorLED", indicatorLed,
3486 "LocationIndicatorActive", locationIndicatorActive,
3487 "AssetTag", assetTag,
3488 "PowerRestorePolicy", powerRestorePolicy,
3489 "PowerMode", powerMode,
3490 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3491 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3492 "Boot/BootSourceOverrideTarget", bootSource,
3493 "Boot/BootSourceOverrideMode", bootType,
3494 "Boot/BootSourceOverrideEnabled", bootEnable,
3495 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003496 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003497 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003498 "Boot/StopBootOnFault", stopBootOnFault,
Ed Tanous22d268c2022-05-19 09:39:07 -07003499 "IdlePowerSaver/Enabled", ipsEnable,
3500 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3501 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3502 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3503 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3504 {
3505 return;
3506 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003507 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003508
Ed Tanousc1e219d2023-06-07 10:34:33 -07003509 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003510
Ed Tanousc1e219d2023-06-07 10:34:33 -07003511 if (assetTag)
3512 {
3513 setAssetTag(asyncResp, *assetTag);
3514 }
James Feistb49ac872019-05-21 15:12:01 -07003515
Ed Tanousc1e219d2023-06-07 10:34:33 -07003516 if (wdtEnable || wdtTimeOutAction)
3517 {
3518 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3519 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003520
Ed Tanousc1e219d2023-06-07 10:34:33 -07003521 if (bootSource || bootType || bootEnable)
3522 {
3523 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3524 }
3525 if (bootAutomaticRetry)
3526 {
3527 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3528 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003529
Ed Tanousc1e219d2023-06-07 10:34:33 -07003530 if (bootAutomaticRetryAttempts)
3531 {
3532 setAutomaticRetryAttempts(asyncResp,
3533 bootAutomaticRetryAttempts.value());
3534 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003535
Ed Tanousc1e219d2023-06-07 10:34:33 -07003536 if (bootTrustedModuleRequired)
3537 {
3538 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3539 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003540
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003541 if (stopBootOnFault)
3542 {
3543 setStopBootOnFault(asyncResp, *stopBootOnFault);
3544 }
3545
Ed Tanousc1e219d2023-06-07 10:34:33 -07003546 if (locationIndicatorActive)
3547 {
George Liu59a17e42022-10-08 09:27:47 +08003548 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003549 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003550
Ed Tanousc1e219d2023-06-07 10:34:33 -07003551 // TODO (Gunnar): Remove IndicatorLED after enough time has
3552 // passed
3553 if (indicatorLed)
3554 {
3555 setIndicatorLedState(asyncResp, *indicatorLed);
3556 asyncResp->res.addHeader(boost::beast::http::field::warning,
3557 "299 - \"IndicatorLED is deprecated. Use "
3558 "LocationIndicatorActive instead.\"");
3559 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003560
Ed Tanousc1e219d2023-06-07 10:34:33 -07003561 if (powerRestorePolicy)
3562 {
3563 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3564 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003565
Ed Tanousc1e219d2023-06-07 10:34:33 -07003566 if (powerMode)
3567 {
3568 setPowerMode(asyncResp, *powerMode);
3569 }
Chris Cain37bbf982021-09-20 10:53:09 -05003570
Ed Tanousc1e219d2023-06-07 10:34:33 -07003571 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3572 {
3573 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3574 ipsExitUtil, ipsExitTime);
3575 }
3576}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303577
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003578inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003579 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003580 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003581 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003582{
3583 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3584 {
3585 return;
3586 }
3587 asyncResp->res.addHeader(
3588 boost::beast::http::field::link,
3589 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3590}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003591
3592/**
3593 * @brief Translates allowed host transitions to redfish string
3594 *
3595 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3596 * @param[out] allowableValues The translated host transition(s)
3597 *
3598 * @return Emplaces correpsonding Redfish translated value(s) in
3599 * allowableValues. If translation not possible, does nothing to
3600 * allowableValues.
3601 */
3602inline void
3603 dbusToRfAllowedHostTransitions(const std::string& dbusAllowedHostTran,
3604 nlohmann::json::array_t& allowableValues)
3605{
3606 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3607 {
3608 allowableValues.emplace_back(resource::ResetType::On);
3609 allowableValues.emplace_back(resource::ResetType::ForceOn);
3610 }
3611 else if (dbusAllowedHostTran ==
3612 "xyz.openbmc_project.State.Host.Transition.Off")
3613 {
3614 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3615 }
3616 else if (dbusAllowedHostTran ==
3617 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3618 {
3619 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3620 }
3621 else if (dbusAllowedHostTran ==
3622 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3623 {
3624 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3625 }
3626 else
3627 {
3628 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3629 }
3630}
3631
3632inline void afterGetAllowedHostTransitions(
3633 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3634 const boost::system::error_code& ec,
3635 const std::vector<std::string>& allowedHostTransitions)
3636{
3637 nlohmann::json::array_t allowableValues;
3638
3639 // Supported on all systems currently
3640 allowableValues.emplace_back(resource::ResetType::ForceOff);
3641 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3642 allowableValues.emplace_back(resource::ResetType::Nmi);
3643
3644 if (ec)
3645 {
Ed Tanouse715d142024-03-07 15:47:37 -08003646 if ((ec.value() ==
3647 boost::system::linux_error::bad_request_descriptor) ||
3648 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003649 {
3650 // Property not implemented so just return defaults
3651 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3652 allowableValues.emplace_back(resource::ResetType::On);
3653 allowableValues.emplace_back(resource::ResetType::ForceOn);
3654 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3655 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3656 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3657 }
3658 else
3659 {
3660 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3661 messages::internalError(asyncResp->res);
3662 return;
3663 }
3664 }
3665 else
3666 {
3667 for (const std::string& transition : allowedHostTransitions)
3668 {
3669 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3670 dbusToRfAllowedHostTransitions(transition, allowableValues);
3671 }
3672 }
3673
3674 nlohmann::json::object_t parameter;
3675 parameter["Name"] = "ResetType";
3676 parameter["Required"] = true;
3677 parameter["DataType"] = "String";
3678 parameter["AllowableValues"] = std::move(allowableValues);
3679 nlohmann::json::array_t parameters;
3680 parameters.emplace_back(std::move(parameter));
3681 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3682}
3683
Ed Tanousc1e219d2023-06-07 10:34:33 -07003684inline void handleSystemCollectionResetActionGet(
3685 crow::App& app, const crow::Request& req,
3686 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3687 const std::string& systemName)
3688{
3689 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3690 {
3691 return;
3692 }
3693 if constexpr (bmcwebEnableMultiHost)
3694 {
3695 // Option currently returns no systems. TBD
3696 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3697 systemName);
3698 return;
3699 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003700
Ed Tanousc1e219d2023-06-07 10:34:33 -07003701 if (systemName == "hypervisor")
3702 {
3703 handleHypervisorResetActionGet(asyncResp);
3704 return;
3705 }
3706
3707 if (systemName != "system")
3708 {
3709 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3710 systemName);
3711 return;
3712 }
3713
3714 asyncResp->res.addHeader(
3715 boost::beast::http::field::link,
3716 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3717
3718 asyncResp->res.jsonValue["@odata.id"] =
3719 "/redfish/v1/Systems/system/ResetActionInfo";
3720 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3721 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3722 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3723
Andrew Geissler33e1f122024-02-26 21:10:16 -06003724 // Look to see if system defines AllowedHostTransitions
3725 sdbusplus::asio::getProperty<std::vector<std::string>>(
3726 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
3727 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
3728 "AllowedHostTransitions",
3729 [asyncResp](const boost::system::error_code& ec,
3730 const std::vector<std::string>& allowedHostTransitions) {
3731 afterGetAllowedHostTransitions(asyncResp, ec, allowedHostTransitions);
3732 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003733}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303734/**
3735 * SystemResetActionInfo derived class for delivering Computer Systems
3736 * ResetType AllowableValues using ResetInfo schema.
3737 */
Ed Tanous100afe52023-06-07 13:30:46 -07003738inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303739{
Ed Tanous100afe52023-06-07 13:30:46 -07003740 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3741 .privileges(redfish::privileges::headComputerSystemCollection)
3742 .methods(boost::beast::http::verb::head)(
3743 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3744
3745 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3746 .privileges(redfish::privileges::getComputerSystemCollection)
3747 .methods(boost::beast::http::verb::get)(
3748 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3749
3750 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3751 .privileges(redfish::privileges::headComputerSystem)
3752 .methods(boost::beast::http::verb::head)(
3753 std::bind_front(handleComputerSystemHead, std::ref(app)));
3754
3755 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3756 .privileges(redfish::privileges::getComputerSystem)
3757 .methods(boost::beast::http::verb::get)(
3758 std::bind_front(handleComputerSystemGet, std::ref(app)));
3759
3760 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3761 .privileges(redfish::privileges::patchComputerSystem)
3762 .methods(boost::beast::http::verb::patch)(
3763 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3764
3765 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3766 .privileges(redfish::privileges::postComputerSystem)
3767 .methods(boost::beast::http::verb::post)(std::bind_front(
3768 handleComputerSystemResetActionPost, std::ref(app)));
3769
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003770 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003771 .privileges(redfish::privileges::headActionInfo)
3772 .methods(boost::beast::http::verb::head)(std::bind_front(
3773 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003774 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003775 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003776 .methods(boost::beast::http::verb::get)(std::bind_front(
3777 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003778}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003779} // namespace redfish