blob: 6b758e7092e53a95e274b8b678839a87c8a83816 [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"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060025#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080026#include "led.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070027#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080028#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "registries/privilege_registry.hpp"
30#include "utils/dbus_utils.hpp"
31#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050032#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080033#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070034#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080035
Andrew Geisslerfc903b32023-05-31 14:15:42 -040036#include <boost/asio/error.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070037#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080038#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060039#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070040#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070041#include <sdbusplus/asio/property.hpp>
Andrew Geisslerfc903b32023-05-31 14:15:42 -040042#include <sdbusplus/message.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020043#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050044
George Liu7a1dbc42022-12-07 16:03:22 +080045#include <array>
Andrew Geissler33e1f122024-02-26 21:10:16 -060046#include <memory>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060047#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080048#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080049#include <variant>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060050#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020051
Ed Tanous1abe55e2018-09-05 08:30:59 -070052namespace redfish
53{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020054
Abhishek Patel5c3e9272021-06-24 10:11:33 -050055const static std::array<std::pair<std::string_view, std::string_view>, 2>
56 protocolToDBusForSystems{
57 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
58
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059/**
60 * @brief Updates the Functional State of DIMMs
61 *
Ed Tanousac106bf2023-06-07 09:24:59 -070062 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050063 * @param[in] dimmState Dimm's Functional state, true/false
64 *
65 * @return None.
66 */
zhanghch058d1b46d2021-04-01 11:18:24 +080067inline void
Ed Tanousac106bf2023-06-07 09:24:59 -070068 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070069 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050070{
Ed Tanous62598e32023-07-17 17:06:25 -070071 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050072
Gunnar Mills4e0453b2020-07-08 14:00:30 -050073 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050074 // Update STATE only if previous State was DISABLED and current Dimm is
75 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070076 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070077 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050078 if (prevMemSummary == "Disabled")
79 {
Ed Tanouse05aec52022-01-25 10:28:56 -080080 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050081 {
Ed Tanousac106bf2023-06-07 09:24:59 -070082 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050083 "Enabled";
84 }
85 }
86}
87
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050088/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050089 * @brief Update "ProcessorSummary" "Status" "State" based on
90 * CPU Functional State
91 *
Ed Tanousac106bf2023-06-07 09:24:59 -070092 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093 * @param[in] cpuFunctionalState is CPU functional true/false
94 *
95 * @return None.
96 */
Ed Tanousac106bf2023-06-07 09:24:59 -070097inline void modifyCpuFunctionalState(
98 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050099{
Ed Tanous62598e32023-07-17 17:06:25 -0700100 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500101
Ed Tanous02cad962022-06-30 16:50:15 -0700102 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700103 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500104
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500105 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106 // Update STATE only if previous State was Non_Functional and current CPU is
107 // Functional.
108 if (prevProcState == "Disabled")
109 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800110 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500111 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700112 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113 "Enabled";
114 }
115 }
116}
117
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500118/*
119 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
120 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700121 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500122 * @param[in] cpuPresenceState CPU present or not
123 *
124 * @return None.
125 */
126inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700127 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500128 bool isCpuPresent)
129{
Ed Tanous62598e32023-07-17 17:06:25 -0700130 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500131
132 if (isCpuPresent)
133 {
134 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700135 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500136 auto* procCountPtr =
137 procCount.get_ptr<nlohmann::json::number_integer_t*>();
138 if (procCountPtr != nullptr)
139 {
140 // shouldn't be possible to be nullptr
141 *procCountPtr += 1;
142 }
143 }
144}
145
Ali Ahmed382d6472021-09-03 16:53:53 -0500146inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700147 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500148 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
149 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500150{
Ed Tanous62598e32023-07-17 17:06:25 -0700151 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500152
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200153 // TODO: Get Model
154
155 const uint16_t* coreCount = nullptr;
156
157 const bool success = sdbusplus::unpackPropertiesNoThrow(
158 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
159
160 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500161 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700162 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200163 return;
164 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200166 if (coreCount != nullptr)
167 {
168 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700169 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200170 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500171
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200172 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500173 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200174 coreCountJson = *coreCount;
175 }
176 else
177 {
178 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500179 }
180 }
181}
182
183/*
184 * @brief Get ProcessorSummary fields
185 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700186 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500187 * @param[in] service dbus service for Cpu Information
188 * @param[in] path dbus path for Cpu
189 *
190 * @return None.
191 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700192inline void
193 getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
194 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500195{
Ed Tanousac106bf2023-06-07 09:24:59 -0700196 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
197 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500198 if (ec3)
199 {
Ed Tanous62598e32023-07-17 17:06:25 -0700200 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500201 return;
202 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700203 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500204 };
205
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500206 // Get the Presence of CPU
207 sdbusplus::asio::getProperty<bool>(
208 *crow::connections::systemBus, service, path,
209 "xyz.openbmc_project.Inventory.Item", "Present",
210 std::move(getCpuPresenceState));
211
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200212 sdbusplus::asio::getAllProperties(
213 *crow::connections::systemBus, service, path,
214 "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700215 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800216 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800217 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700218 if (ec2)
219 {
Ed Tanous62598e32023-07-17 17:06:25 -0700220 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700221 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700222 return;
223 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700224 getProcessorProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500225 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500226}
227
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500228/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500229 * @brief processMemoryProperties fields
230 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700231 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500232 * @param[in] DBUS properties for memory
233 *
234 * @return None.
235 */
236inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700237 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500238 const dbus::utility::DBusPropertiesMap& properties)
239{
Ed Tanous62598e32023-07-17 17:06:25 -0700240 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500241
242 if (properties.empty())
243 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500244 return;
245 }
246
247 const size_t* memorySizeInKB = nullptr;
248
249 const bool success = sdbusplus::unpackPropertiesNoThrow(
250 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
251 memorySizeInKB);
252
253 if (!success)
254 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700255 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500256 return;
257 }
258
259 if (memorySizeInKB != nullptr)
260 {
261 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700262 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500263 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500264 if (preValue == nullptr)
265 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700266 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500267 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500268 }
269 else
270 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700271 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500272 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
273 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500274 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500275 }
276}
277
278/*
279 * @brief Get getMemorySummary fields
280 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700281 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500282 * @param[in] service dbus service for memory Information
283 * @param[in] path dbus path for memory
284 *
285 * @return None.
286 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700287inline void
288 getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
289 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500290{
291 sdbusplus::asio::getAllProperties(
292 *crow::connections::systemBus, service, path,
293 "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700294 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500295 path](const boost::system::error_code& ec2,
296 const dbus::utility::DBusPropertiesMap& properties) {
297 if (ec2)
298 {
Ed Tanous62598e32023-07-17 17:06:25 -0700299 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700300 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500301 return;
302 }
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500303 processMemoryProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500304 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500305}
306
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500307inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
308 const boost::system::error_code& ec,
309 const dbus::utility::DBusPropertiesMap& properties)
310{
311 if (ec)
312 {
313 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
314 messages::internalError(asyncResp->res);
315 return;
316 }
317 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
318
319 const std::string* uUID = nullptr;
320
321 const bool success = sdbusplus::unpackPropertiesNoThrow(
322 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
323
324 if (!success)
325 {
326 messages::internalError(asyncResp->res);
327 return;
328 }
329
330 if (uUID != nullptr)
331 {
332 std::string valueStr = *uUID;
333 if (valueStr.size() == 32)
334 {
335 valueStr.insert(8, 1, '-');
336 valueStr.insert(13, 1, '-');
337 valueStr.insert(18, 1, '-');
338 valueStr.insert(23, 1, '-');
339 }
340 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
341 asyncResp->res.jsonValue["UUID"] = valueStr;
342 }
343}
344
345inline void
346 afterGetInventory(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
347 const boost::system::error_code& ec,
348 const dbus::utility::DBusPropertiesMap& propertiesList)
349{
350 if (ec)
351 {
352 // doesn't have to include this
353 // interface
354 return;
355 }
356 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
357
358 const std::string* partNumber = nullptr;
359 const std::string* serialNumber = nullptr;
360 const std::string* manufacturer = nullptr;
361 const std::string* model = nullptr;
362 const std::string* subModel = nullptr;
363
364 const bool success = sdbusplus::unpackPropertiesNoThrow(
365 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
366 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
367 "Model", model, "SubModel", subModel);
368
369 if (!success)
370 {
371 messages::internalError(asyncResp->res);
372 return;
373 }
374
375 if (partNumber != nullptr)
376 {
377 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
378 }
379
380 if (serialNumber != nullptr)
381 {
382 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
383 }
384
385 if (manufacturer != nullptr)
386 {
387 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
388 }
389
390 if (model != nullptr)
391 {
392 asyncResp->res.jsonValue["Model"] = *model;
393 }
394
395 if (subModel != nullptr)
396 {
397 asyncResp->res.jsonValue["SubModel"] = *subModel;
398 }
399
400 // Grab the bios version
401 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
402 "BiosVersion", false);
403}
404
405inline void
406 afterGetAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
407 const boost::system::error_code& ec,
408 const std::string& value)
409{
410 if (ec)
411 {
412 // doesn't have to include this
413 // interface
414 return;
415 }
416
417 asyncResp->res.jsonValue["AssetTag"] = value;
418}
419
420inline void afterSystemGetSubTree(
421 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500422 const boost::system::error_code& ec,
423 const dbus::utility::MapperGetSubTreeResponse& subtree)
424{
425 if (ec)
426 {
427 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
428 messages::internalError(asyncResp->res);
429 return;
430 }
431 // Iterate over all retrieved ObjectPaths.
432 for (const std::pair<
433 std::string,
434 std::vector<std::pair<std::string, std::vector<std::string>>>>&
435 object : subtree)
436 {
437 const std::string& path = object.first;
438 BMCWEB_LOG_DEBUG("Got path: {}", path);
439 const std::vector<std::pair<std::string, std::vector<std::string>>>&
440 connectionNames = object.second;
441 if (connectionNames.empty())
442 {
443 continue;
444 }
445
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500446 // This is not system, so check if it's cpu, dimm, UUID or
447 // BiosVer
448 for (const auto& connection : connectionNames)
449 {
450 for (const auto& interfaceName : connection.second)
451 {
452 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
453 {
454 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
455
456 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500457 }
458 else if (interfaceName ==
459 "xyz.openbmc_project.Inventory.Item.Cpu")
460 {
461 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
462
463 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500464 }
465 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
466 {
467 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
468
469 sdbusplus::asio::getAllProperties(
470 *crow::connections::systemBus, connection.first, path,
471 "xyz.openbmc_project.Common.UUID",
472 [asyncResp](const boost::system::error_code& ec3,
473 const dbus::utility::DBusPropertiesMap&
474 properties) {
475 afterGetUUID(asyncResp, ec3, properties);
476 });
477 }
478 else if (interfaceName ==
479 "xyz.openbmc_project.Inventory.Item.System")
480 {
481 sdbusplus::asio::getAllProperties(
482 *crow::connections::systemBus, connection.first, path,
483 "xyz.openbmc_project.Inventory.Decorator.Asset",
484 [asyncResp](const boost::system::error_code& ec3,
485 const dbus::utility::DBusPropertiesMap&
486 properties) {
487 afterGetInventory(asyncResp, ec3, properties);
488 });
489
490 sdbusplus::asio::getProperty<std::string>(
491 *crow::connections::systemBus, connection.first, path,
492 "xyz.openbmc_project.Inventory.Decorator."
493 "AssetTag",
494 "AssetTag",
495 std::bind_front(afterGetAssetTag, asyncResp));
496 }
497 }
498 }
499 }
500}
501
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500502/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700503 * @brief Retrieves computer system properties over dbus
504 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700505 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700506 *
507 * @return None.
508 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700509inline void
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500510 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700511{
Ed Tanous62598e32023-07-17 17:06:25 -0700512 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800513 constexpr std::array<std::string_view, 5> interfaces = {
514 "xyz.openbmc_project.Inventory.Decorator.Asset",
515 "xyz.openbmc_project.Inventory.Item.Cpu",
516 "xyz.openbmc_project.Inventory.Item.Dimm",
517 "xyz.openbmc_project.Inventory.Item.System",
518 "xyz.openbmc_project.Common.UUID",
519 };
520 dbus::utility::getSubTree(
521 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500522 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700523}
524
525/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700526 * @brief Retrieves host state properties over dbus
527 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700528 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Ed Tanous6c34de42018-08-29 13:37:36 -0700529 *
530 * @return None.
531 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700532inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700533{
Ed Tanous62598e32023-07-17 17:06:25 -0700534 BMCWEB_LOG_DEBUG("Get host information.");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700535 sdbusplus::asio::getProperty<std::string>(
536 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
537 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
538 "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700539 [asyncResp](const boost::system::error_code& ec,
540 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700541 if (ec)
542 {
543 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700544 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700545 // Service not available, no error, just don't return
546 // host state info
Ed Tanous62598e32023-07-17 17:06:25 -0700547 BMCWEB_LOG_DEBUG("Service not available {}", ec);
Ed Tanous6c34de42018-08-29 13:37:36 -0700548 return;
549 }
Ed Tanous62598e32023-07-17 17:06:25 -0700550 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700551 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700552 return;
553 }
Ed Tanous66173382018-08-15 18:20:59 -0700554
Ed Tanous62598e32023-07-17 17:06:25 -0700555 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
Ed Tanous002d39b2022-05-31 08:59:27 -0700556 // Verify Host State
557 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
558 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700559 asyncResp->res.jsonValue["PowerState"] = "On";
560 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700561 }
562 else if (hostState ==
563 "xyz.openbmc_project.State.Host.HostState.Quiesced")
564 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700565 asyncResp->res.jsonValue["PowerState"] = "On";
566 asyncResp->res.jsonValue["Status"]["State"] = "Quiesced";
Ed Tanous002d39b2022-05-31 08:59:27 -0700567 }
568 else if (hostState ==
569 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
570 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700571 asyncResp->res.jsonValue["PowerState"] = "On";
572 asyncResp->res.jsonValue["Status"]["State"] = "InTest";
Ed Tanous002d39b2022-05-31 08:59:27 -0700573 }
574 else if (
575 hostState ==
576 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
577 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700578 asyncResp->res.jsonValue["PowerState"] = "PoweringOn";
579 asyncResp->res.jsonValue["Status"]["State"] = "Starting";
Ed Tanous002d39b2022-05-31 08:59:27 -0700580 }
581 else if (hostState ==
582 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
583 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700584 asyncResp->res.jsonValue["PowerState"] = "PoweringOff";
585 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700586 }
587 else
588 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700589 asyncResp->res.jsonValue["PowerState"] = "Off";
590 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700591 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500592 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700593}
594
595/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500596 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530597 *
598 * @param[in] dbusSource The boot source in DBUS speak.
599 *
600 * @return Returns as a string, the boot source in Redfish terms. If translation
601 * cannot be done, returns an empty string.
602 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000603inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530604{
605 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
606 {
607 return "None";
608 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700609 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530610 {
611 return "Hdd";
612 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700613 if (dbusSource ==
614 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615 {
616 return "Cd";
617 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700618 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530619 {
620 return "Pxe";
621 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700622 if (dbusSource ==
623 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700624 {
625 return "Usb";
626 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700627 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530628}
629
630/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300631 * @brief Translates boot type DBUS property value to redfish.
632 *
633 * @param[in] dbusType The boot type in DBUS speak.
634 *
635 * @return Returns as a string, the boot type in Redfish terms. If translation
636 * cannot be done, returns an empty string.
637 */
638inline std::string dbusToRfBootType(const std::string& dbusType)
639{
640 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
641 {
642 return "Legacy";
643 }
644 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
645 {
646 return "UEFI";
647 }
648 return "";
649}
650
651/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500652 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530653 *
654 * @param[in] dbusMode The boot mode in DBUS speak.
655 *
656 * @return Returns as a string, the boot mode in Redfish terms. If translation
657 * cannot be done, returns an empty string.
658 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000659inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530660{
661 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
662 {
663 return "None";
664 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700665 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530666 {
667 return "Diags";
668 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700669 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530670 {
671 return "BiosSetup";
672 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700673 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674}
675
676/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600677 * @brief Translates boot progress DBUS property value to redfish.
678 *
679 * @param[in] dbusBootProgress The boot progress in DBUS speak.
680 *
681 * @return Returns as a string, the boot progress in Redfish terms. If
682 * translation cannot be done, returns "None".
683 */
684inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
685{
686 // Now convert the D-Bus BootProgress to the appropriate Redfish
687 // enum
688 std::string rfBpLastState = "None";
689 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
690 "ProgressStages.Unspecified")
691 {
692 rfBpLastState = "None";
693 }
694 else if (dbusBootProgress ==
695 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
696 "PrimaryProcInit")
697 {
698 rfBpLastState = "PrimaryProcessorInitializationStarted";
699 }
700 else if (dbusBootProgress ==
701 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
702 "BusInit")
703 {
704 rfBpLastState = "BusInitializationStarted";
705 }
706 else if (dbusBootProgress ==
707 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
708 "MemoryInit")
709 {
710 rfBpLastState = "MemoryInitializationStarted";
711 }
712 else if (dbusBootProgress ==
713 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
714 "SecondaryProcInit")
715 {
716 rfBpLastState = "SecondaryProcessorInitializationStarted";
717 }
718 else if (dbusBootProgress ==
719 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
720 "PCIInit")
721 {
722 rfBpLastState = "PCIResourceConfigStarted";
723 }
724 else if (dbusBootProgress ==
725 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
726 "SystemSetup")
727 {
728 rfBpLastState = "SetupEntered";
729 }
730 else if (dbusBootProgress ==
731 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
732 "SystemInitComplete")
733 {
734 rfBpLastState = "SystemHardwareInitializationComplete";
735 }
736 else if (dbusBootProgress ==
737 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
738 "OSStart")
739 {
740 rfBpLastState = "OSBootStarted";
741 }
742 else if (dbusBootProgress ==
743 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
744 "OSRunning")
745 {
746 rfBpLastState = "OSRunning";
747 }
748 else
749 {
Ed Tanous62598e32023-07-17 17:06:25 -0700750 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600751 // Just return the default
752 }
753 return rfBpLastState;
754}
755
756/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500757 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530758 *
759 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700760 * @param[out] bootSource The DBus source
761 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530762 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700763 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530764 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700765inline int
766 assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
767 const std::string& rfSource, std::string& bootSource,
768 std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530769{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300770 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
771 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700772
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 if (rfSource == "None")
774 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700775 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530776 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700777 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
780 }
781 else if (rfSource == "Hdd")
782 {
783 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
784 }
785 else if (rfSource == "Diags")
786 {
787 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
788 }
789 else if (rfSource == "Cd")
790 {
791 bootSource =
792 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
793 }
794 else if (rfSource == "BiosSetup")
795 {
796 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530797 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700798 else if (rfSource == "Usb")
799 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700800 bootSource =
801 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700802 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530803 else
804 {
Ed Tanous62598e32023-07-17 17:06:25 -0700805 BMCWEB_LOG_DEBUG(
806 "Invalid property value for BootSourceOverrideTarget: {}",
807 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700808 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700809 "BootSourceTargetOverride");
810 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530811 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700812 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530813}
Ali Ahmed19817712021-06-29 17:01:52 -0500814
Andrew Geissler978b8802020-11-19 13:36:40 -0600815/**
816 * @brief Retrieves boot progress of the system
817 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700818 * @param[in] asyncResp Shared pointer for generating response message.
Andrew Geissler978b8802020-11-19 13:36:40 -0600819 *
820 * @return None.
821 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700822inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600823{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700824 sdbusplus::asio::getProperty<std::string>(
825 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
826 "/xyz/openbmc_project/state/host0",
827 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700828 [asyncResp](const boost::system::error_code& ec,
829 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700830 if (ec)
831 {
832 // BootProgress is an optional object so just do nothing if
833 // not found
834 return;
835 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600836
Ed Tanous62598e32023-07-17 17:06:25 -0700837 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600838
Ed Tanousac106bf2023-06-07 09:24:59 -0700839 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700840 dbusToRfBootProgress(bootProgressStr);
Patrick Williams5a39f772023-10-20 11:20:21 -0500841 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600842}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530843
844/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000845 * @brief Retrieves boot progress Last Update of the system
846 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700847 * @param[in] asyncResp Shared pointer for generating response message.
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000848 *
849 * @return None.
850 */
851inline void getBootProgressLastStateTime(
Ed Tanousac106bf2023-06-07 09:24:59 -0700852 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000853{
854 sdbusplus::asio::getProperty<uint64_t>(
855 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
856 "/xyz/openbmc_project/state/host0",
857 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700858 [asyncResp](const boost::system::error_code& ec,
859 const uint64_t lastStateTime) {
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000860 if (ec)
861 {
Ed Tanous62598e32023-07-17 17:06:25 -0700862 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000863 return;
864 }
865
866 // BootProgressLastUpdate is the last time the BootProgress property
867 // was updated. The time is the Epoch time, number of microseconds
868 // since 1 Jan 1970 00::00::00 UTC."
869 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
870 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
871
872 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -0700873 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000874 redfish::time_utils::getDateTimeUintUs(lastStateTime);
Patrick Williams5a39f772023-10-20 11:20:21 -0500875 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000876}
877
878/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300879 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300880 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700881 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882 *
883 * @return None.
884 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300885
Ed Tanousac106bf2023-06-07 09:24:59 -0700886inline void
887 getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300888{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700889 sdbusplus::asio::getProperty<std::string>(
890 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
891 "/xyz/openbmc_project/control/host0/boot",
892 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700893 [asyncResp](const boost::system::error_code& ec,
894 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700895 if (ec)
896 {
897 // not an error, don't have to have the interface
898 return;
899 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300900
Ed Tanous62598e32023-07-17 17:06:25 -0700901 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300902
Ed Tanousac106bf2023-06-07 09:24:59 -0700903 asyncResp->res
904 .jsonValue["Boot"]
905 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700906 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300907
Ed Tanous002d39b2022-05-31 08:59:27 -0700908 auto rfType = dbusToRfBootType(bootType);
909 if (rfType.empty())
910 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700911 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700912 return;
913 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300914
Ed Tanousac106bf2023-06-07 09:24:59 -0700915 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Patrick Williams5a39f772023-10-20 11:20:21 -0500916 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300917}
918
919/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300920 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530921 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700922 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923 *
924 * @return None.
925 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300926
Ed Tanousac106bf2023-06-07 09:24:59 -0700927inline void
928 getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530929{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700930 sdbusplus::asio::getProperty<std::string>(
931 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
932 "/xyz/openbmc_project/control/host0/boot",
933 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700934 [asyncResp](const boost::system::error_code& ec,
935 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700936 if (ec)
937 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -0500938 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700939 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700940 return;
941 }
942
Ed Tanous62598e32023-07-17 17:06:25 -0700943 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
Ed Tanous002d39b2022-05-31 08:59:27 -0700944
Ed Tanousac106bf2023-06-07 09:24:59 -0700945 asyncResp->res
Ed Tanous002d39b2022-05-31 08:59:27 -0700946 .jsonValue["Boot"]
947 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
948 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
949
950 if (bootModeStr !=
951 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
952 {
953 auto rfMode = dbusToRfBootMode(bootModeStr);
954 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530955 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700956 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700957 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530958 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700959 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500960 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530961}
962
963/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300964 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530965 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700966 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967 *
968 * @return None.
969 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300970
971inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700972 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530973{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700974 sdbusplus::asio::getProperty<std::string>(
975 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
976 "/xyz/openbmc_project/control/host0/boot",
977 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanousac106bf2023-06-07 09:24:59 -0700978 [asyncResp](const boost::system::error_code& ec,
979 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700980 if (ec)
981 {
Nan Zhou5ef735c2022-06-22 05:24:21 +0000982 if (ec.value() == boost::asio::error::host_unreachable)
983 {
984 return;
985 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -0500986 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700987 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700988 return;
989 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990
Ed Tanous62598e32023-07-17 17:06:25 -0700991 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530992
Ed Tanous002d39b2022-05-31 08:59:27 -0700993 auto rfSource = dbusToRfBootSource(bootSourceStr);
994 if (!rfSource.empty())
995 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700996 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
997 rfSource;
Ed Tanous002d39b2022-05-31 08:59:27 -0700998 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300999
Ed Tanous002d39b2022-05-31 08:59:27 -07001000 // Get BootMode as BootSourceOverrideTarget is constructed
1001 // from both BootSource and BootMode
Ed Tanousac106bf2023-06-07 09:24:59 -07001002 getBootOverrideMode(asyncResp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001003 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301004}
1005
1006/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001007 * @brief This functions abstracts all the logic behind getting a
1008 * "BootSourceOverrideEnabled" property from an overall boot override enable
1009 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301010 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001011 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301012 *
1013 * @return None.
1014 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301015
Ed Tanousac106bf2023-06-07 09:24:59 -07001016inline void processBootOverrideEnable(
1017 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1018 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001019{
1020 if (!bootOverrideEnableSetting)
1021 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001022 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1023 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001024 return;
1025 }
1026
1027 // If boot source override is enabled, we need to check 'one_time'
1028 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001029 sdbusplus::asio::getProperty<bool>(
1030 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1031 "/xyz/openbmc_project/control/host0/boot/one_time",
1032 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001033 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001034 if (ec)
1035 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001036 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001037 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001038 return;
1039 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301040
Ed Tanous002d39b2022-05-31 08:59:27 -07001041 if (oneTimeSetting)
1042 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001043 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1044 "Once";
Ed Tanous002d39b2022-05-31 08:59:27 -07001045 }
1046 else
1047 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001048 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001049 "Continuous";
1050 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001051 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301052}
1053
1054/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001055 * @brief Retrieves boot override enable over DBUS
1056 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001057 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001058 *
1059 * @return None.
1060 */
1061
1062inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001063 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001064{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001065 sdbusplus::asio::getProperty<bool>(
1066 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1067 "/xyz/openbmc_project/control/host0/boot",
1068 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001069 [asyncResp](const boost::system::error_code& ec,
1070 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001071 if (ec)
1072 {
Nan Zhou5ef735c2022-06-22 05:24:21 +00001073 if (ec.value() == boost::asio::error::host_unreachable)
1074 {
1075 return;
1076 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001077 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001078 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001079 return;
1080 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001081
Ed Tanousac106bf2023-06-07 09:24:59 -07001082 processBootOverrideEnable(asyncResp, bootOverrideEnable);
Patrick Williams5a39f772023-10-20 11:20:21 -05001083 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001084}
1085
1086/**
1087 * @brief Retrieves boot source override properties
1088 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001089 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001090 *
1091 * @return None.
1092 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001093inline void
1094 getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001095{
Ed Tanous62598e32023-07-17 17:06:25 -07001096 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001097
Ed Tanousac106bf2023-06-07 09:24:59 -07001098 getBootOverrideSource(asyncResp);
1099 getBootOverrideType(asyncResp);
1100 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001101}
1102
1103/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001104 * @brief Retrieves the Last Reset Time
1105 *
1106 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1107 * and power off. Even though this is the "system" Redfish object look at the
1108 * chassis D-Bus interface for the LastStateChangeTime since this has the
1109 * last power operation time.
1110 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001111 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001112 *
1113 * @return None.
1114 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001115inline void
1116 getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001117{
Ed Tanous62598e32023-07-17 17:06:25 -07001118 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001119
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001120 sdbusplus::asio::getProperty<uint64_t>(
1121 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1122 "/xyz/openbmc_project/state/chassis0",
1123 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001124 [asyncResp](const boost::system::error_code& ec,
1125 uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001126 if (ec)
1127 {
Ed Tanous62598e32023-07-17 17:06:25 -07001128 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001129 return;
1130 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001131
Ed Tanous002d39b2022-05-31 08:59:27 -07001132 // LastStateChangeTime is epoch time, in milliseconds
1133 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1134 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001135
Ed Tanous002d39b2022-05-31 08:59:27 -07001136 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -07001137 asyncResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001138 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001139 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001140}
1141
1142/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001143 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1144 *
1145 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1146 * corresponding property "AttemptsLeft" that keeps track of the amount of
1147 * automatic retry attempts left are hosted in phosphor-state-manager through
1148 * dbus.
1149 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001150 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001151 *
1152 * @return None.
1153 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001154inline void getAutomaticRebootAttempts(
1155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001156{
Ed Tanous62598e32023-07-17 17:06:25 -07001157 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001158
1159 sdbusplus::asio::getAllProperties(
1160 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1161 "/xyz/openbmc_project/state/host0",
1162 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001163 [asyncResp{asyncResp}](
1164 const boost::system::error_code& ec,
1165 const dbus::utility::DBusPropertiesMap& propertiesList) {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001166 if (ec)
1167 {
1168 if (ec.value() != EBADR)
1169 {
Ed Tanous62598e32023-07-17 17:06:25 -07001170 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001171 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001172 }
1173 return;
1174 }
1175
1176 const uint32_t* attemptsLeft = nullptr;
1177 const uint32_t* retryAttempts = nullptr;
1178
1179 const bool success = sdbusplus::unpackPropertiesNoThrow(
1180 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1181 attemptsLeft, "RetryAttempts", retryAttempts);
1182
1183 if (!success)
1184 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001185 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001186 return;
1187 }
1188
1189 if (attemptsLeft != nullptr)
1190 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001191 asyncResp->res
1192 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001193 *attemptsLeft;
1194 }
1195
1196 if (retryAttempts != nullptr)
1197 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001198 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001199 *retryAttempts;
1200 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001201 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001202}
1203
1204/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001205 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1206 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001207 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001208 *
1209 * @return None.
1210 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001211inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001212 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001213{
Ed Tanous62598e32023-07-17 17:06:25 -07001214 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001215
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001216 sdbusplus::asio::getProperty<bool>(
1217 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1218 "/xyz/openbmc_project/control/host0/auto_reboot",
1219 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001220 [asyncResp](const boost::system::error_code& ec,
1221 bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001222 if (ec)
1223 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001224 if (ec.value() != EBADR)
1225 {
Ed Tanous62598e32023-07-17 17:06:25 -07001226 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001227 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001228 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001229 return;
1230 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001231
Ed Tanous62598e32023-07-17 17:06:25 -07001232 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
Ed Tanous002d39b2022-05-31 08:59:27 -07001233 if (autoRebootEnabled)
1234 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001235 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001236 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001237 }
1238 else
1239 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001240 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1241 "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -07001242 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001243 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001244
Ed Tanous002d39b2022-05-31 08:59:27 -07001245 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1246 // and RetryAttempts. OpenBMC only supports Disabled and
1247 // RetryAttempts.
Ed Tanousac106bf2023-06-07 09:24:59 -07001248 asyncResp->res
1249 .jsonValue["Boot"]["AutomaticRetryConfig@Redfish.AllowableValues"] =
1250 {"Disabled", "RetryAttempts"};
Patrick Williams5a39f772023-10-20 11:20:21 -05001251 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001252}
1253
1254/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001255 * @brief Sets RetryAttempts
1256 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001257 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001258 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1259 *
1260 *@return None.
1261 */
1262
Ed Tanousac106bf2023-06-07 09:24:59 -07001263inline void setAutomaticRetryAttempts(
1264 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1265 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001266{
Ed Tanous62598e32023-07-17 17:06:25 -07001267 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001268 setDbusProperty(
1269 asyncResp, "xyz.openbmc_project.State.Host",
1270 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001271 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001272 "Boot/AutomaticRetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001273}
1274
Ed Tanous8d69c662023-06-21 10:29:06 -07001275inline computer_system::PowerRestorePolicyTypes
1276 redfishPowerRestorePolicyFromDbus(std::string_view value)
1277{
1278 if (value ==
1279 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1280 {
1281 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1282 }
1283 if (value ==
1284 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1285 {
1286 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1287 }
1288 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001289 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001290 {
1291 return computer_system::PowerRestorePolicyTypes::LastState;
1292 }
1293 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1294 {
1295 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1296 }
1297 return computer_system::PowerRestorePolicyTypes::Invalid;
1298}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001299/**
George Liuc6a620f2020-04-10 17:18:11 +08001300 * @brief Retrieves power restore policy over DBUS.
1301 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001302 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001303 *
1304 * @return None.
1305 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001306inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001307 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001308{
Ed Tanous62598e32023-07-17 17:06:25 -07001309 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001310
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001311 sdbusplus::asio::getProperty<std::string>(
1312 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1313 "/xyz/openbmc_project/control/host0/power_restore_policy",
1314 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001315 [asyncResp](const boost::system::error_code& ec,
1316 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001317 if (ec)
1318 {
Ed Tanous62598e32023-07-17 17:06:25 -07001319 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001320 return;
1321 }
Ed Tanous8d69c662023-06-21 10:29:06 -07001322 computer_system::PowerRestorePolicyTypes restore =
1323 redfishPowerRestorePolicyFromDbus(policy);
1324 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -07001325 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001326 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001327 return;
1328 }
George Liuc6a620f2020-04-10 17:18:11 +08001329
Ed Tanous8d69c662023-06-21 10:29:06 -07001330 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
Patrick Williams5a39f772023-10-20 11:20:21 -05001331 });
George Liuc6a620f2020-04-10 17:18:11 +08001332}
1333
1334/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001335 * @brief Stop Boot On Fault over DBUS.
1336 *
1337 * @param[in] asyncResp Shared pointer for generating response message.
1338 *
1339 * @return None.
1340 */
1341inline void
1342 getStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1343{
Ed Tanous62598e32023-07-17 17:06:25 -07001344 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001345
1346 sdbusplus::asio::getProperty<bool>(
1347 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1348 "/xyz/openbmc_project/logging/settings",
1349 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1350 [asyncResp](const boost::system::error_code& ec, bool value) {
1351 if (ec)
1352 {
1353 if (ec.value() != EBADR)
1354 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001355 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001356 messages::internalError(asyncResp->res);
1357 }
1358 return;
1359 }
1360
1361 if (value)
1362 {
1363 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "AnyFault";
1364 }
1365 else
1366 {
1367 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "Never";
1368 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001369 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001370}
1371
1372/**
Ali Ahmed19817712021-06-29 17:01:52 -05001373 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1374 * TPM is required for booting the host.
1375 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001376 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001377 *
1378 * @return None.
1379 */
1380inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001381 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001382{
Ed Tanous62598e32023-07-17 17:06:25 -07001383 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001384 constexpr std::array<std::string_view, 1> interfaces = {
1385 "xyz.openbmc_project.Control.TPM.Policy"};
1386 dbus::utility::getSubTree(
1387 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001388 [asyncResp](const boost::system::error_code& ec,
1389 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001390 if (ec)
1391 {
Ed Tanous62598e32023-07-17 17:06:25 -07001392 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}",
1393 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001394 // This is an optional D-Bus object so just return if
1395 // error occurs
1396 return;
1397 }
1398 if (subtree.empty())
1399 {
1400 // As noted above, this is an optional interface so just return
1401 // if there is no instance found
1402 return;
1403 }
1404
1405 /* When there is more than one TPMEnable object... */
1406 if (subtree.size() > 1)
1407 {
Ed Tanous62598e32023-07-17 17:06:25 -07001408 BMCWEB_LOG_DEBUG(
1409 "DBUS response has more than 1 TPM Enable object:{}",
1410 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001411 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001412 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001413 return;
1414 }
1415
1416 // Make sure the Dbus response map has a service and objectPath
1417 // field
1418 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1419 {
Ed Tanous62598e32023-07-17 17:06:25 -07001420 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001421 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001422 return;
1423 }
1424
1425 const std::string& path = subtree[0].first;
1426 const std::string& serv = subtree[0].second.begin()->first;
1427
1428 // Valid TPM Enable object found, now reading the current value
1429 sdbusplus::asio::getProperty<bool>(
1430 *crow::connections::systemBus, serv, path,
1431 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanousac106bf2023-06-07 09:24:59 -07001432 [asyncResp](const boost::system::error_code& ec2,
1433 bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001434 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001435 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001436 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001437 ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001438 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001439 return;
1440 }
1441
Ed Tanous002d39b2022-05-31 08:59:27 -07001442 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001443 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001444 asyncResp->res
1445 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001446 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001447 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001448 else
1449 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001450 asyncResp->res
1451 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001452 "Disabled";
1453 }
George Liue99073f2022-12-09 11:06:16 +08001454 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001455 });
Ali Ahmed19817712021-06-29 17:01:52 -05001456}
1457
1458/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001459 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1460 * TPM is required for booting the host.
1461 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001462 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001463 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1464 *
1465 * @return None.
1466 */
1467inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001468 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001469{
Ed Tanous62598e32023-07-17 17:06:25 -07001470 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
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,
George Liue99073f2022-12-09 11:06:16 +08001476 tpmRequired](const boost::system::error_code& ec,
1477 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001478 if (ec)
1479 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001480 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001481 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001482 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001483 return;
1484 }
1485 if (subtree.empty())
1486 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001487 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07001488 "TrustedModuleRequiredToBoot");
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 if (serv.empty())
1516 {
Ed Tanous62598e32023-07-17 17:06:25 -07001517 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001518 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001519 return;
1520 }
1521
1522 // Valid TPM Enable object found, now setting the value
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001523 setDbusProperty(asyncResp, serv, path,
1524 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1525 "Boot/TrustedModuleRequiredToBoot", tpmRequired);
Patrick Williams5a39f772023-10-20 11:20:21 -05001526 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001527}
1528
1529/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301530 * @brief Sets boot properties into DBUS object(s).
1531 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001532 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001533 * @param[in] bootType The boot type to set.
1534 * @return Integer error code.
1535 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001536inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001537 const std::optional<std::string>& bootType)
1538{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001539 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001540
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001541 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001542 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001543 return;
1544 }
1545
1546 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001547 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001548 // Figure out which DBUS interface and property to use
1549 if (*bootType == "Legacy")
1550 {
1551 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1552 }
1553 else if (*bootType == "UEFI")
1554 {
1555 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1556 }
1557 else
1558 {
Ed Tanous62598e32023-07-17 17:06:25 -07001559 BMCWEB_LOG_DEBUG("Invalid property value for "
1560 "BootSourceOverrideMode: {}",
1561 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001562 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001563 "BootSourceOverrideMode");
1564 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001565 }
1566
1567 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001568 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001569
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001570 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1571 sdbusplus::message::object_path(
1572 "/xyz/openbmc_project/control/host0/boot"),
1573 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1574 "Boot/BootSourceOverrideMode", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001575}
1576
1577/**
1578 * @brief Sets boot properties into DBUS object(s).
1579 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001580 * @param[in] asyncResp Shared pointer for generating response
1581 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001582 * @param[in] bootType The boot type to set.
1583 * @return Integer error code.
1584 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001585inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001586 const std::optional<std::string>& bootEnable)
1587{
1588 if (!bootEnable)
1589 {
1590 return;
1591 }
1592 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001593 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001594
1595 bool bootOverrideEnable = false;
1596 bool bootOverridePersistent = false;
1597 // Figure out which DBUS interface and property to use
1598 if (*bootEnable == "Disabled")
1599 {
1600 bootOverrideEnable = false;
1601 }
1602 else if (*bootEnable == "Once")
1603 {
1604 bootOverrideEnable = true;
1605 bootOverridePersistent = false;
1606 }
1607 else if (*bootEnable == "Continuous")
1608 {
1609 bootOverrideEnable = true;
1610 bootOverridePersistent = true;
1611 }
1612 else
1613 {
Ed Tanous62598e32023-07-17 17:06:25 -07001614 BMCWEB_LOG_DEBUG(
1615 "Invalid property value for BootSourceOverrideEnabled: {}",
1616 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001617 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001618 "BootSourceOverrideEnabled");
1619 return;
1620 }
1621
1622 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001623 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001624
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001625 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1626 sdbusplus::message::object_path(
1627 "/xyz/openbmc_project/control/host0/boot"),
1628 "xyz.openbmc_project.Object.Enable", "Enabled",
1629 "Boot/BootSourceOverrideEnabled", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001630
1631 if (!bootOverrideEnable)
1632 {
1633 return;
1634 }
1635
1636 // In case boot override is enabled we need to set correct value for the
1637 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001638 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1639 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001640
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001641 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1642 sdbusplus::message::object_path(
1643 "/xyz/openbmc_project/control/host0/boot/one_time"),
1644 "xyz.openbmc_project.Object.Enable", "Enabled",
1645 "Boot/BootSourceOverrideEnabled", !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001646}
1647
1648/**
1649 * @brief Sets boot properties into DBUS object(s).
1650 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001651 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301652 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301653 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001654 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301655 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001656inline void
1657 setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1658 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301659{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001660 std::string bootSourceStr;
1661 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001662
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001663 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301664 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001665 return;
1666 }
1667
1668 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001669 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001670 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001671 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1672 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001673 {
Ed Tanous62598e32023-07-17 17:06:25 -07001674 BMCWEB_LOG_DEBUG(
1675 "Invalid property value for BootSourceOverrideTarget: {}",
1676 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001677 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001678 "BootSourceTargetOverride");
1679 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001680 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301681
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001682 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001683 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1684 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001685
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001686 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1687 sdbusplus::message::object_path(
1688 "/xyz/openbmc_project/control/host0/boot"),
1689 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1690 "Boot/BootSourceOverrideTarget", bootSourceStr);
1691 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1692 sdbusplus::message::object_path(
1693 "/xyz/openbmc_project/control/host0/boot"),
1694 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1695 "Boot/BootSourceOverrideTarget", bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001696}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001697
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001698/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001699 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301700 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001701 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301702 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001703 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301704 * @param[in] bootEnable The boot override enable from incoming RF request.
1705 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001706 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301707 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001708
Ed Tanousac106bf2023-06-07 09:24:59 -07001709inline void
1710 setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1711 const std::optional<std::string>& bootSource,
1712 const std::optional<std::string>& bootType,
1713 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301714{
Ed Tanous62598e32023-07-17 17:06:25 -07001715 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301716
Ed Tanousac106bf2023-06-07 09:24:59 -07001717 setBootModeOrSource(asyncResp, bootSource);
1718 setBootType(asyncResp, bootType);
1719 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301720}
1721
George Liuc6a620f2020-04-10 17:18:11 +08001722/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001723 * @brief Sets AssetTag
1724 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001725 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001726 * @param[in] assetTag "AssetTag" from request.
1727 *
1728 * @return None.
1729 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001730inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001731 const std::string& assetTag)
1732{
George Liue99073f2022-12-09 11:06:16 +08001733 constexpr std::array<std::string_view, 1> interfaces = {
1734 "xyz.openbmc_project.Inventory.Item.System"};
1735 dbus::utility::getSubTree(
1736 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001737 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001738 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001739 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001740 if (ec)
1741 {
Ed Tanous62598e32023-07-17 17:06:25 -07001742 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001743 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001744 return;
1745 }
1746 if (subtree.empty())
1747 {
Ed Tanous62598e32023-07-17 17:06:25 -07001748 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001749 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001750 return;
1751 }
1752 // Assume only 1 system D-Bus object
1753 // Throw an error if there is more than 1
1754 if (subtree.size() > 1)
1755 {
Ed Tanous62598e32023-07-17 17:06:25 -07001756 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001757 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001758 return;
1759 }
1760 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1761 {
Ed Tanous62598e32023-07-17 17:06:25 -07001762 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001763 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001764 return;
1765 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001766
Ed Tanous002d39b2022-05-31 08:59:27 -07001767 const std::string& path = subtree[0].first;
1768 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001769
Ed Tanous002d39b2022-05-31 08:59:27 -07001770 if (service.empty())
1771 {
Ed Tanous62598e32023-07-17 17:06:25 -07001772 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001773 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001774 return;
1775 }
1776
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001777 setDbusProperty(asyncResp, service, path,
1778 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1779 "AssetTag", "AssetTag", assetTag);
Patrick Williams5a39f772023-10-20 11:20:21 -05001780 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001781}
1782
1783/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001784 * @brief Validate the specified stopBootOnFault is valid and return the
1785 * stopBootOnFault name associated with that string
1786 *
1787 * @param[in] stopBootOnFaultString String representing the desired
1788 * stopBootOnFault
1789 *
1790 * @return stopBootOnFault value or empty if incoming value is not valid
1791 */
1792inline std::optional<bool>
1793 validstopBootOnFault(const std::string& stopBootOnFaultString)
1794{
1795 if (stopBootOnFaultString == "AnyFault")
1796 {
1797 return true;
1798 }
1799
1800 if (stopBootOnFaultString == "Never")
1801 {
1802 return false;
1803 }
1804
1805 return std::nullopt;
1806}
1807
1808/**
1809 * @brief Sets stopBootOnFault
1810 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001811 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001812 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1813 *
1814 * @return None.
1815 */
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001816inline void
1817 setStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1818 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001819{
Ed Tanous62598e32023-07-17 17:06:25 -07001820 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001821
1822 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1823 if (!stopBootEnabled)
1824 {
Ed Tanous62598e32023-07-17 17:06:25 -07001825 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1826 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001827 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001828 "StopBootOnFault");
1829 return;
1830 }
1831
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001832 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1833 sdbusplus::message::object_path(
1834 "/xyz/openbmc_project/logging/settings"),
1835 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1836 "Boot/StopBootOnFault", *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001837}
1838
1839/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001840 * @brief Sets automaticRetry (Auto Reboot)
1841 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001842 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001843 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1844 *
1845 * @return None.
1846 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001847inline void
1848 setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1849 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001850{
Ed Tanous62598e32023-07-17 17:06:25 -07001851 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001852
1853 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001854 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001855
1856 if (automaticRetryConfig == "Disabled")
1857 {
1858 autoRebootEnabled = false;
1859 }
1860 else if (automaticRetryConfig == "RetryAttempts")
1861 {
1862 autoRebootEnabled = true;
1863 }
1864 else
1865 {
Ed Tanous62598e32023-07-17 17:06:25 -07001866 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1867 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001868 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001869 "AutomaticRetryConfig");
1870 return;
1871 }
1872
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001873 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1874 sdbusplus::message::object_path(
1875 "/xyz/openbmc_project/control/host0/auto_reboot"),
1876 "xyz.openbmc_project.Control.Boot.RebootPolicy",
1877 "AutoReboot", "Boot/AutomaticRetryConfig",
1878 autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001879}
1880
Ed Tanous8d69c662023-06-21 10:29:06 -07001881inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1882{
1883 if (policy == "AlwaysOn")
1884 {
1885 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1886 }
1887 if (policy == "AlwaysOff")
1888 {
1889 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1890 }
1891 if (policy == "LastState")
1892 {
1893 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1894 }
1895 return "";
1896}
1897
Gunnar Mills69f35302020-05-17 16:06:31 -05001898/**
George Liuc6a620f2020-04-10 17:18:11 +08001899 * @brief Sets power restore policy properties.
1900 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001901 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001902 * @param[in] policy power restore policy properties from request.
1903 *
1904 * @return None.
1905 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001906inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001907 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous8d69c662023-06-21 10:29:06 -07001908 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001909{
Ed Tanous62598e32023-07-17 17:06:25 -07001910 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001911
Ed Tanous8d69c662023-06-21 10:29:06 -07001912 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001913
Ed Tanous8d69c662023-06-21 10:29:06 -07001914 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001915 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001916 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001917 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001918 return;
1919 }
1920
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001921 setDbusProperty(
1922 asyncResp, "xyz.openbmc_project.Settings",
1923 sdbusplus::message::object_path(
1924 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001925 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001926 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001927}
1928
AppaRao Pulia6349912019-10-18 17:16:08 +05301929/**
1930 * @brief Retrieves provisioning status
1931 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001932 * @param[in] asyncResp Shared pointer for completing asynchronous
1933 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301934 *
1935 * @return None.
1936 */
Ed Tanous25b54db2024-04-17 15:40:31 -07001937inline void
1938 getProvisioningStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301939{
Ed Tanous62598e32023-07-17 17:06:25 -07001940 BMCWEB_LOG_DEBUG("Get OEM information.");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001941 sdbusplus::asio::getAllProperties(
1942 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1943 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001944 [asyncResp](const boost::system::error_code& ec,
1945 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001946 nlohmann::json& oemPFR =
Ed Tanousac106bf2023-06-07 09:24:59 -07001947 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1948 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001949 "#OemComputerSystem.OpenBmc";
1950 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001951
Ed Tanous002d39b2022-05-31 08:59:27 -07001952 if (ec)
1953 {
Ed Tanous62598e32023-07-17 17:06:25 -07001954 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001955 // not an error, don't have to have the interface
1956 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1957 return;
1958 }
1959
1960 const bool* provState = nullptr;
1961 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001962
1963 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001964 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1965 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001966
1967 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001968 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001969 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001970 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001971 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301972
Ed Tanous002d39b2022-05-31 08:59:27 -07001973 if ((provState == nullptr) || (lockState == nullptr))
1974 {
Ed Tanous62598e32023-07-17 17:06:25 -07001975 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
Ed Tanousac106bf2023-06-07 09:24:59 -07001976 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001977 return;
1978 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301979
Ed Tanous25b54db2024-04-17 15:40:31 -07001980 if (*provState)
Ed Tanous002d39b2022-05-31 08:59:27 -07001981 {
Ed Tanous25b54db2024-04-17 15:40:31 -07001982 if (*lockState)
AppaRao Pulia6349912019-10-18 17:16:08 +05301983 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001984 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301985 }
1986 else
1987 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001988 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301989 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001990 }
1991 else
1992 {
1993 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1994 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001995 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301996}
AppaRao Pulia6349912019-10-18 17:16:08 +05301997
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301998/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06001999 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002000 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002001 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002002 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002003 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002004 */
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002005inline computer_system::PowerMode
2006 translatePowerModeString(const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002007{
Chris Cainb6655102024-02-01 14:35:33 -06002008 using PowerMode = computer_system::PowerMode;
2009
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002010 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002011 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002012 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002013 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002014 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002015 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002016 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002017 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002018 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002019 if (modeString ==
2020 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002021 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002022 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002023 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002024 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002025 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2026 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002027 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002028 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002029 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002030 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2031 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002032 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002033 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002034 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002035 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2036 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002037 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002038 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002039 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002040 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002041 return PowerMode::OEM;
2042 }
2043 // Any other values would be invalid
2044 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2045 return PowerMode::Invalid;
2046}
2047
2048inline void
2049 afterGetPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2050 const boost::system::error_code& ec,
2051 const dbus::utility::DBusPropertiesMap& properties)
2052{
2053 if (ec)
2054 {
2055 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2056 messages::internalError(asyncResp->res);
2057 return;
2058 }
2059
2060 std::string powerMode;
2061 const std::vector<std::string>* allowedModes = nullptr;
2062 const bool success = sdbusplus::unpackPropertiesNoThrow(
2063 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2064 "AllowedPowerModes", allowedModes);
2065
2066 if (!success)
2067 {
2068 messages::internalError(asyncResp->res);
2069 return;
2070 }
2071
2072 nlohmann::json::array_t modeList;
2073 if (allowedModes == nullptr)
2074 {
2075 modeList.emplace_back("Static");
2076 modeList.emplace_back("MaximumPerformance");
2077 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002078 }
2079 else
2080 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002081 for (const auto& aMode : *allowedModes)
2082 {
2083 computer_system::PowerMode modeValue =
2084 translatePowerModeString(aMode);
2085 if (modeValue == computer_system::PowerMode::Invalid)
2086 {
2087 messages::internalError(asyncResp->res);
2088 continue;
2089 }
2090 modeList.emplace_back(modeValue);
2091 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002092 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002093 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002094
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002095 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2096 const computer_system::PowerMode modeValue =
2097 translatePowerModeString(powerMode);
2098 if (modeValue == computer_system::PowerMode::Invalid)
2099 {
2100 messages::internalError(asyncResp->res);
2101 return;
2102 }
2103 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2104}
Chris Cain3a2d04242021-05-28 16:57:10 -05002105/**
2106 * @brief Retrieves system power mode
2107 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002108 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002109 *
2110 * @return None.
2111 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002112inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002113{
Ed Tanous62598e32023-07-17 17:06:25 -07002114 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002115
2116 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002117 constexpr std::array<std::string_view, 1> interfaces = {
2118 "xyz.openbmc_project.Control.Power.Mode"};
2119 dbus::utility::getSubTree(
2120 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002121 [asyncResp](const boost::system::error_code& ec,
2122 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002123 if (ec)
2124 {
Ed Tanous62598e32023-07-17 17:06:25 -07002125 BMCWEB_LOG_DEBUG("DBUS response error on Power.Mode GetSubTree {}",
2126 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002127 // This is an optional D-Bus object so just return if
2128 // error occurs
2129 return;
2130 }
2131 if (subtree.empty())
2132 {
2133 // As noted above, this is an optional interface so just return
2134 // if there is no instance found
2135 return;
2136 }
2137 if (subtree.size() > 1)
2138 {
2139 // More then one PowerMode object is not supported and is an
2140 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002141 BMCWEB_LOG_DEBUG(
2142 "Found more than 1 system D-Bus Power.Mode objects: {}",
2143 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002144 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002145 return;
2146 }
2147 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2148 {
Ed Tanous62598e32023-07-17 17:06:25 -07002149 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002150 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002151 return;
2152 }
2153 const std::string& path = subtree[0].first;
2154 const std::string& service = subtree[0].second.begin()->first;
2155 if (service.empty())
2156 {
Ed Tanous62598e32023-07-17 17:06:25 -07002157 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002158 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002159 return;
2160 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002161
2162 // Valid Power Mode object found, now read the mode properties
2163 sdbusplus::asio::getAllProperties(
Ed Tanous002d39b2022-05-31 08:59:27 -07002164 *crow::connections::systemBus, service, path,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002165 "xyz.openbmc_project.Control.Power.Mode",
Ed Tanousac106bf2023-06-07 09:24:59 -07002166 [asyncResp](const boost::system::error_code& ec2,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002167 const dbus::utility::DBusPropertiesMap& properties) {
2168 afterGetPowerMode(asyncResp, ec2, properties);
George Liue99073f2022-12-09 11:06:16 +08002169 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002170 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002171}
2172
2173/**
2174 * @brief Validate the specified mode is valid and return the PowerMode
2175 * name associated with that string
2176 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002177 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002178 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002179 *
2180 * @return PowerMode value or empty string if mode is not valid
2181 */
2182inline std::string
Ed Tanousac106bf2023-06-07 09:24:59 -07002183 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cainb6655102024-02-01 14:35:33 -06002184 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002185{
Chris Cainb6655102024-02-01 14:35:33 -06002186 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002187 std::string mode;
2188
Chris Cainb6655102024-02-01 14:35:33 -06002189 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002190 {
2191 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2192 }
Chris Cainb6655102024-02-01 14:35:33 -06002193 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002194 {
George Liu0fda0f12021-11-16 10:06:17 +08002195 mode =
2196 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002197 }
Chris Cainb6655102024-02-01 14:35:33 -06002198 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002199 {
2200 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2201 }
Chris Cainb6655102024-02-01 14:35:33 -06002202 else if (modeValue == PowerMode::BalancedPerformance)
2203 {
2204 mode =
2205 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2206 }
2207 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2208 {
2209 mode =
2210 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2211 }
2212 else if (modeValue == PowerMode::EfficiencyFavorPower)
2213 {
2214 mode =
2215 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2216 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002217 else
2218 {
Chris Cainb6655102024-02-01 14:35:33 -06002219 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002220 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002221 }
2222 return mode;
2223}
2224
2225/**
2226 * @brief Sets system power mode.
2227 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002228 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002229 * @param[in] pmode System power mode from request.
2230 *
2231 * @return None.
2232 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002233inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002234 const std::string& pmode)
2235{
Ed Tanous62598e32023-07-17 17:06:25 -07002236 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002237
Ed Tanousac106bf2023-06-07 09:24:59 -07002238 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002239 if (powerMode.empty())
2240 {
2241 return;
2242 }
2243
2244 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002245 constexpr std::array<std::string_view, 1> interfaces = {
2246 "xyz.openbmc_project.Control.Power.Mode"};
2247 dbus::utility::getSubTree(
2248 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002249 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002250 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002251 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002252 if (ec)
2253 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002254 BMCWEB_LOG_ERROR("DBUS response error on Power.Mode GetSubTree {}",
Ed Tanous62598e32023-07-17 17:06:25 -07002255 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002256 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002257 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002258 return;
2259 }
2260 if (subtree.empty())
2261 {
2262 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002263 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002264 "PowerMode");
2265 return;
2266 }
2267 if (subtree.size() > 1)
2268 {
2269 // More then one PowerMode object is not supported and is an
2270 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002271 BMCWEB_LOG_DEBUG(
2272 "Found more than 1 system D-Bus Power.Mode objects: {}",
2273 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002274 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002275 return;
2276 }
2277 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2278 {
Ed Tanous62598e32023-07-17 17:06:25 -07002279 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002280 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002281 return;
2282 }
2283 const std::string& path = subtree[0].first;
2284 const std::string& service = subtree[0].second.begin()->first;
2285 if (service.empty())
2286 {
Ed Tanous62598e32023-07-17 17:06:25 -07002287 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002288 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002289 return;
2290 }
2291
Ed Tanous62598e32023-07-17 17:06:25 -07002292 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002293
2294 // Set the Power Mode property
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002295 setDbusProperty(asyncResp, service, path,
2296 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2297 "PowerMode", powerMode);
Patrick Williams5a39f772023-10-20 11:20:21 -05002298 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002299}
2300
2301/**
Yong Li51709ff2019-09-30 14:13:04 +08002302 * @brief Translates watchdog timeout action DBUS property value to redfish.
2303 *
2304 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2305 *
2306 * @return Returns as a string, the timeout action in Redfish terms. If
2307 * translation cannot be done, returns an empty string.
2308 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002309inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002310{
2311 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2312 {
2313 return "None";
2314 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002315 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002316 {
2317 return "ResetSystem";
2318 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002319 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002320 {
2321 return "PowerDown";
2322 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002323 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002324 {
2325 return "PowerCycle";
2326 }
2327
2328 return "";
2329}
2330
2331/**
Yong Lic45f0082019-10-10 14:19:01 +08002332 *@brief Translates timeout action from Redfish to DBUS property value.
2333 *
2334 *@param[in] rfAction The timeout action in Redfish.
2335 *
2336 *@return Returns as a string, the time_out action as expected by DBUS.
2337 *If translation cannot be done, returns an empty string.
2338 */
2339
Ed Tanous23a21a12020-07-25 04:45:05 +00002340inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002341{
2342 if (rfAction == "None")
2343 {
2344 return "xyz.openbmc_project.State.Watchdog.Action.None";
2345 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002346 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002347 {
2348 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2349 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002350 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002351 {
2352 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2353 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002354 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002355 {
2356 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2357 }
2358
2359 return "";
2360}
2361
2362/**
Yong Li51709ff2019-09-30 14:13:04 +08002363 * @brief Retrieves host watchdog timer properties over DBUS
2364 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002365 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002366 *
2367 * @return None.
2368 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002369inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002370 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002371{
Ed Tanous62598e32023-07-17 17:06:25 -07002372 BMCWEB_LOG_DEBUG("Get host watchodg");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002373 sdbusplus::asio::getAllProperties(
2374 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2375 "/xyz/openbmc_project/watchdog/host0",
2376 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002377 [asyncResp](const boost::system::error_code& ec,
2378 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002379 if (ec)
2380 {
2381 // watchdog service is stopped
Ed Tanous62598e32023-07-17 17:06:25 -07002382 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002383 return;
2384 }
2385
Ed Tanous62598e32023-07-17 17:06:25 -07002386 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002387
2388 nlohmann::json& hostWatchdogTimer =
Ed Tanousac106bf2023-06-07 09:24:59 -07002389 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002390
2391 // watchdog service is running/enabled
2392 hostWatchdogTimer["Status"]["State"] = "Enabled";
2393
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002394 const bool* enabled = nullptr;
2395 const std::string* expireAction = nullptr;
2396
2397 const bool success = sdbusplus::unpackPropertiesNoThrow(
2398 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2399 "ExpireAction", expireAction);
2400
2401 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002402 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002403 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002404 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002405 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002406
2407 if (enabled != nullptr)
2408 {
2409 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2410 }
2411
2412 if (expireAction != nullptr)
2413 {
2414 std::string action = dbusToRfWatchdogAction(*expireAction);
2415 if (action.empty())
2416 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002417 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002418 return;
2419 }
2420 hostWatchdogTimer["TimeoutAction"] = action;
2421 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002422 });
Yong Li51709ff2019-09-30 14:13:04 +08002423}
2424
2425/**
Yong Lic45f0082019-10-10 14:19:01 +08002426 * @brief Sets Host WatchDog Timer properties.
2427 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002428 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002429 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2430 * RF request.
2431 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2432 *
2433 * @return None.
2434 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002435inline void
2436 setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2437 const std::optional<bool> wdtEnable,
2438 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002439{
Ed Tanous62598e32023-07-17 17:06:25 -07002440 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002441
2442 if (wdtTimeOutAction)
2443 {
2444 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2445 // check if TimeOut Action is Valid
2446 if (wdtTimeOutActStr.empty())
2447 {
Ed Tanous62598e32023-07-17 17:06:25 -07002448 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2449 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002450 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002451 "TimeoutAction");
2452 return;
2453 }
2454
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002455 setDbusProperty(asyncResp, "xyz.openbmc_project.Watchdog",
2456 sdbusplus::message::object_path(
2457 "/xyz/openbmc_project/watchdog/host0"),
2458 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2459 "HostWatchdogTimer/TimeoutAction", wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002460 }
2461
2462 if (wdtEnable)
2463 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002464 setDbusProperty(asyncResp, "xyz.openbmc_project.Watchdog",
2465 sdbusplus::message::object_path(
2466 "/xyz/openbmc_project/watchdog/host0"),
2467 "xyz.openbmc_project.State.Watchdog", "Enabled",
2468 "HostWatchdogTimer/FunctionEnabled", *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002469 }
2470}
2471
Chris Cain37bbf982021-09-20 10:53:09 -05002472/**
2473 * @brief Parse the Idle Power Saver properties into json
2474 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002475 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002476 * @param[in] properties IPS property data from DBus.
2477 *
2478 * @return true if successful
2479 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002480inline bool
Ed Tanousac106bf2023-06-07 09:24:59 -07002481 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002482 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002483{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002484 const bool* enabled = nullptr;
2485 const uint8_t* enterUtilizationPercent = nullptr;
2486 const uint64_t* enterDwellTime = nullptr;
2487 const uint8_t* exitUtilizationPercent = nullptr;
2488 const uint64_t* exitDwellTime = nullptr;
2489
2490 const bool success = sdbusplus::unpackPropertiesNoThrow(
2491 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002492 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2493 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2494 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002495
2496 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002497 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002498 return false;
2499 }
2500
2501 if (enabled != nullptr)
2502 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002503 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002504 }
2505
2506 if (enterUtilizationPercent != nullptr)
2507 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002508 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002509 *enterUtilizationPercent;
2510 }
2511
2512 if (enterDwellTime != nullptr)
2513 {
2514 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002515 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002516 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2517 .count();
2518 }
2519
2520 if (exitUtilizationPercent != nullptr)
2521 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002522 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002523 *exitUtilizationPercent;
2524 }
2525
2526 if (exitDwellTime != nullptr)
2527 {
2528 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002529 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002530 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2531 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002532 }
2533
2534 return true;
2535}
2536
2537/**
2538 * @brief Retrieves host watchdog timer properties over DBUS
2539 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002540 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002541 *
2542 * @return None.
2543 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002544inline void
2545 getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002546{
Ed Tanous62598e32023-07-17 17:06:25 -07002547 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002548
2549 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002550 constexpr std::array<std::string_view, 1> interfaces = {
2551 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2552 dbus::utility::getSubTree(
2553 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002554 [asyncResp](const boost::system::error_code& ec,
2555 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002556 if (ec)
2557 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002558 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002559 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2560 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002561 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002562 return;
2563 }
2564 if (subtree.empty())
2565 {
2566 // This is an optional interface so just return
2567 // if there is no instance found
Ed Tanous62598e32023-07-17 17:06:25 -07002568 BMCWEB_LOG_DEBUG("No instances found");
Ed Tanous002d39b2022-05-31 08:59:27 -07002569 return;
2570 }
2571 if (subtree.size() > 1)
2572 {
2573 // More then one PowerIdlePowerSaver object is not supported and
2574 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002575 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2576 "Power.IdlePowerSaver objects: {}",
2577 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002578 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002579 return;
2580 }
2581 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2582 {
Ed Tanous62598e32023-07-17 17:06:25 -07002583 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002584 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002585 return;
2586 }
2587 const std::string& path = subtree[0].first;
2588 const std::string& service = subtree[0].second.begin()->first;
2589 if (service.empty())
2590 {
Ed Tanous62598e32023-07-17 17:06:25 -07002591 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002592 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002593 return;
2594 }
2595
2596 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002597 sdbusplus::asio::getAllProperties(
2598 *crow::connections::systemBus, service, path,
2599 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanousac106bf2023-06-07 09:24:59 -07002600 [asyncResp](const boost::system::error_code& ec2,
2601 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002602 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002603 {
Ed Tanous62598e32023-07-17 17:06:25 -07002604 BMCWEB_LOG_ERROR(
2605 "DBUS response error on IdlePowerSaver GetAll: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002606 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002607 return;
2608 }
2609
Ed Tanousac106bf2023-06-07 09:24:59 -07002610 if (!parseIpsProperties(asyncResp, properties))
Ed Tanous002d39b2022-05-31 08:59:27 -07002611 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002612 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002613 return;
2614 }
George Liue99073f2022-12-09 11:06:16 +08002615 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002616 });
Chris Cain37bbf982021-09-20 10:53:09 -05002617
Ed Tanous62598e32023-07-17 17:06:25 -07002618 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002619}
2620
2621/**
2622 * @brief Sets Idle Power Saver properties.
2623 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002624 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002625 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2626 * RF request.
2627 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2628 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2629 * before entering idle state.
2630 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2631 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2632 * before exiting idle state
2633 *
2634 * @return None.
2635 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002636inline void
2637 setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2638 const std::optional<bool> ipsEnable,
2639 const std::optional<uint8_t> ipsEnterUtil,
2640 const std::optional<uint64_t> ipsEnterTime,
2641 const std::optional<uint8_t> ipsExitUtil,
2642 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002643{
Ed Tanous62598e32023-07-17 17:06:25 -07002644 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002645
2646 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002647 constexpr std::array<std::string_view, 1> interfaces = {
2648 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2649 dbus::utility::getSubTree(
2650 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002651 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002652 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002653 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002654 if (ec)
2655 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002656 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002657 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2658 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002659 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002660 return;
2661 }
2662 if (subtree.empty())
2663 {
2664 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002665 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002666 "IdlePowerSaver");
2667 return;
2668 }
2669 if (subtree.size() > 1)
2670 {
2671 // More then one PowerIdlePowerSaver object is not supported and
2672 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002673 BMCWEB_LOG_DEBUG(
2674 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2675 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002676 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002677 return;
2678 }
2679 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2680 {
Ed Tanous62598e32023-07-17 17:06:25 -07002681 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002682 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002683 return;
2684 }
2685 const std::string& path = subtree[0].first;
2686 const std::string& service = subtree[0].second.begin()->first;
2687 if (service.empty())
2688 {
Ed Tanous62598e32023-07-17 17:06:25 -07002689 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002690 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002691 return;
2692 }
Chris Cain37bbf982021-09-20 10:53:09 -05002693
Ed Tanous002d39b2022-05-31 08:59:27 -07002694 // Valid Power IdlePowerSaver object found, now set any values that
2695 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002696
Ed Tanous002d39b2022-05-31 08:59:27 -07002697 if (ipsEnable)
2698 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002699 setDbusProperty(asyncResp, service, path,
2700 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2701 "Enabled", "IdlePowerSaver/Enabled", *ipsEnable);
Ed Tanous002d39b2022-05-31 08:59:27 -07002702 }
2703 if (ipsEnterUtil)
2704 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002705 setDbusProperty(asyncResp, service, path,
2706 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2707 "EnterUtilizationPercent",
2708 "IdlePowerSaver/EnterUtilizationPercent",
2709 *ipsEnterUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002710 }
2711 if (ipsEnterTime)
2712 {
2713 // Convert from seconds into milliseconds for DBus
2714 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002715 setDbusProperty(asyncResp, service, path,
2716 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2717 "EnterDwellTime",
2718 "IdlePowerSaver/EnterDwellTimeSeconds",
2719 timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002720 }
2721 if (ipsExitUtil)
2722 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002723 setDbusProperty(asyncResp, service, path,
2724 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2725 "ExitUtilizationPercent",
2726 "IdlePowerSaver/ExitUtilizationPercent",
2727 *ipsExitUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002728 }
2729 if (ipsExitTime)
2730 {
2731 // Convert from seconds into milliseconds for DBus
2732 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002733 setDbusProperty(asyncResp, service, path,
2734 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2735 "ExitDwellTime",
2736 "IdlePowerSaver/ExitDwellTimeSeconds",
2737 timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002738 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002739 });
Chris Cain37bbf982021-09-20 10:53:09 -05002740
Ed Tanous62598e32023-07-17 17:06:25 -07002741 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002742}
2743
Ed Tanousc1e219d2023-06-07 10:34:33 -07002744inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002745 crow::App& app, const crow::Request& req,
2746 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2747{
2748 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2749 {
2750 return;
2751 }
2752 asyncResp->res.addHeader(
2753 boost::beast::http::field::link,
2754 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2755}
2756
Ed Tanousc1e219d2023-06-07 10:34:33 -07002757inline void handleComputerSystemCollectionGet(
2758 crow::App& app, const crow::Request& req,
2759 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2760{
2761 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2762 {
2763 return;
2764 }
2765
2766 asyncResp->res.addHeader(
2767 boost::beast::http::field::link,
2768 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2769 asyncResp->res.jsonValue["@odata.type"] =
2770 "#ComputerSystemCollection.ComputerSystemCollection";
2771 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2772 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2773
2774 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2775 ifaceArray = nlohmann::json::array();
Ed Tanous25b54db2024-04-17 15:40:31 -07002776 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002777 {
2778 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2779 // Option currently returns no systems. TBD
2780 return;
2781 }
2782 asyncResp->res.jsonValue["Members@odata.count"] = 1;
2783 nlohmann::json::object_t system;
Ed Tanous253f11b2024-05-16 09:38:31 -07002784 system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
2785 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002786 ifaceArray.emplace_back(std::move(system));
2787 sdbusplus::asio::getProperty<std::string>(
2788 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2789 "/xyz/openbmc_project/network/hypervisor",
2790 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
2791 [asyncResp](const boost::system::error_code& ec2,
2792 const std::string& /*hostName*/) {
2793 if (ec2)
2794 {
2795 return;
2796 }
2797 auto val = asyncResp->res.jsonValue.find("Members@odata.count");
2798 if (val == asyncResp->res.jsonValue.end())
2799 {
Ed Tanous62598e32023-07-17 17:06:25 -07002800 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002801 return;
2802 }
2803 uint64_t* count = val->get_ptr<uint64_t*>();
2804 if (count == nullptr)
2805 {
Ed Tanous62598e32023-07-17 17:06:25 -07002806 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002807 return;
2808 }
2809 *count = *count + 1;
Ed Tanous62598e32023-07-17 17:06:25 -07002810 BMCWEB_LOG_DEBUG("Hypervisor is available");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002811 nlohmann::json& ifaceArray2 = asyncResp->res.jsonValue["Members"];
2812 nlohmann::json::object_t hypervisor;
2813 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2814 ifaceArray2.emplace_back(std::move(hypervisor));
Patrick Williams5a39f772023-10-20 11:20:21 -05002815 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07002816}
2817
Yong Lic45f0082019-10-10 14:19:01 +08002818/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 * Function transceives data with dbus directly.
2820 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002821inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002822{
Patrick Williams89492a12023-05-10 07:51:34 -05002823 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2824 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2825 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002826 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002827 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002828
2829 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002830 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002831 if (ec)
2832 {
Ed Tanous62598e32023-07-17 17:06:25 -07002833 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002834 messages::internalError(asyncResp->res);
2835 return;
2836 }
2837 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05002838 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839 serviceName, objectPath, interfaceName, method);
2840}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002841
Ed Tanousc1e219d2023-06-07 10:34:33 -07002842inline void handleComputerSystemResetActionPost(
2843 crow::App& app, const crow::Request& req,
2844 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2845 const std::string& systemName)
2846{
2847 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2848 {
2849 return;
2850 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002851 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002852 {
2853 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2854 systemName);
2855 return;
2856 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002857 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002858 {
2859 // Option currently returns no systems. TBD
2860 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2861 systemName);
2862 return;
2863 }
2864 std::string resetType;
2865 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2866 {
2867 return;
2868 }
2869
2870 // Get the command and host vs. chassis
2871 std::string command;
2872 bool hostCommand = true;
2873 if ((resetType == "On") || (resetType == "ForceOn"))
2874 {
2875 command = "xyz.openbmc_project.State.Host.Transition.On";
2876 hostCommand = true;
2877 }
2878 else if (resetType == "ForceOff")
2879 {
2880 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2881 hostCommand = false;
2882 }
2883 else if (resetType == "ForceRestart")
2884 {
2885 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2886 hostCommand = true;
2887 }
2888 else if (resetType == "GracefulShutdown")
2889 {
2890 command = "xyz.openbmc_project.State.Host.Transition.Off";
2891 hostCommand = true;
2892 }
2893 else if (resetType == "GracefulRestart")
2894 {
2895 command =
2896 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2897 hostCommand = true;
2898 }
2899 else if (resetType == "PowerCycle")
2900 {
2901 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2902 hostCommand = true;
2903 }
2904 else if (resetType == "Nmi")
2905 {
2906 doNMI(asyncResp);
2907 return;
2908 }
2909 else
2910 {
2911 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2912 return;
2913 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002914 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002915
2916 if (hostCommand)
2917 {
Ed Tanousd02aad32024-02-13 14:43:34 -08002918 setDbusProperty(asyncResp, "xyz.openbmc_project.State.Host",
2919 statePath / "host0", "xyz.openbmc_project.State.Host",
2920 "RequestedHostTransition", "Reset", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002921 }
2922 else
2923 {
Ed Tanousd02aad32024-02-13 14:43:34 -08002924 setDbusProperty(asyncResp, "xyz.openbmc_project.State.Chassis",
2925 statePath / "chassis0",
2926 "xyz.openbmc_project.State.Chassis",
2927 "RequestedPowerTransition", "Reset", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002928 }
2929}
2930
Ed Tanousc1e219d2023-06-07 10:34:33 -07002931inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002932 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002933 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2934 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002935{
2936 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2937 {
2938 return;
2939 }
2940
2941 asyncResp->res.addHeader(
2942 boost::beast::http::field::link,
2943 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2944}
2945
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002946inline void afterPortRequest(
2947 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2948 const boost::system::error_code& ec,
2949 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2950{
2951 if (ec)
2952 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002953 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002954 messages::internalError(asyncResp->res);
2955 return;
2956 }
2957 for (const auto& data : socketData)
2958 {
2959 const std::string& socketPath = get<0>(data);
2960 const std::string& protocolName = get<1>(data);
2961 bool isProtocolEnabled = get<2>(data);
2962 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2963 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2964 // need to retrieve port number for
2965 // obmc-console-ssh service
2966 if (protocolName == "SSH")
2967 {
2968 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002969 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002970 int portNumber) {
2971 if (ec1)
2972 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002973 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002974 messages::internalError(asyncResp->res);
2975 return;
2976 }
2977 nlohmann::json& dataJson1 =
2978 asyncResp->res.jsonValue["SerialConsole"];
2979 dataJson1[protocolName]["Port"] = portNumber;
2980 });
2981 }
2982 }
2983}
Ed Tanousc1e219d2023-06-07 10:34:33 -07002984
2985inline void
2986 handleComputerSystemGet(crow::App& app, const crow::Request& req,
2987 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2988 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002989{
Ed Tanousc1e219d2023-06-07 10:34:33 -07002990 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2991 {
2992 return;
2993 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06002994
Ed Tanous25b54db2024-04-17 15:40:31 -07002995 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002996 {
2997 // Option currently returns no systems. TBD
2998 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2999 systemName);
3000 return;
3001 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003002
Ed Tanousc1e219d2023-06-07 10:34:33 -07003003 if (systemName == "hypervisor")
3004 {
3005 handleHypervisorSystemGet(asyncResp);
3006 return;
3007 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003008
Ed Tanous253f11b2024-05-16 09:38:31 -07003009 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003010 {
3011 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3012 systemName);
3013 return;
3014 }
3015 asyncResp->res.addHeader(
3016 boost::beast::http::field::link,
3017 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3018 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003019 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003020 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3021 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003022 asyncResp->res.jsonValue["SystemType"] = "Physical";
3023 asyncResp->res.jsonValue["Description"] = "Computer System";
3024 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003025 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003026 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003027 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3028 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003029
Ed Tanous253f11b2024-05-16 09:38:31 -07003030 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3031 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3032 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3033 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3034 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3035 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003036 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003037 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3038 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003039
Ed Tanousc1e219d2023-06-07 10:34:33 -07003040 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003041 boost::urls::format(
3042 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3043 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003044 asyncResp->res
3045 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003046 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3047 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003048
Ed Tanous253f11b2024-05-16 09:38:31 -07003049 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3050 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3051 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3052 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003053
Ed Tanousc1e219d2023-06-07 10:34:33 -07003054 nlohmann::json::array_t managedBy;
3055 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003056 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3057 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003058 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3059 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3060 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003061
Ed Tanousc1e219d2023-06-07 10:34:33 -07003062 // Fill in SerialConsole info
3063 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3064 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003065
Ed Tanousc1e219d2023-06-07 10:34:33 -07003066 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3067 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3068 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3069 "Press ~. to exit console";
3070 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3071 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003072
Ed Tanous25b54db2024-04-17 15:40:31 -07003073 if constexpr (BMCWEB_KVM)
3074 {
3075 // Fill in GraphicalConsole info
3076 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3077 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3078 4;
3079 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3080 nlohmann::json::array_t({"KVMIP"});
3081 }
James Feistb49ac872019-05-21 15:12:01 -07003082
Ed Tanousc1e219d2023-06-07 10:34:33 -07003083 getMainChassisId(asyncResp,
3084 [](const std::string& chassisId,
3085 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3086 nlohmann::json::array_t chassisArray;
3087 nlohmann::json& chassis = chassisArray.emplace_back();
3088 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3089 chassisId);
3090 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3091 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003092
George Liu59a17e42022-10-08 09:27:47 +08003093 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003094 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3095 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003096 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003097 getHostState(asyncResp);
3098 getBootProperties(asyncResp);
3099 getBootProgress(asyncResp);
3100 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003101 pcie_util::getPCIeDeviceList(asyncResp,
3102 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003103 getHostWatchdogTimer(asyncResp);
3104 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003105 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003106 getAutomaticRetryPolicy(asyncResp);
3107 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003108 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3109 {
3110 getProvisioningStatus(asyncResp);
3111 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003112 getTrustedModuleRequiredToBoot(asyncResp);
3113 getPowerMode(asyncResp);
3114 getIdlePowerSaver(asyncResp);
3115}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003116
Ed Tanousc1e219d2023-06-07 10:34:33 -07003117inline void handleComputerSystemPatch(
3118 crow::App& app, const crow::Request& req,
3119 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3120 const std::string& systemName)
3121{
3122 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3123 {
3124 return;
3125 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003126 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003127 {
3128 // Option currently returns no systems. TBD
3129 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3130 systemName);
3131 return;
3132 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003133 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003134 {
3135 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3136 systemName);
3137 return;
3138 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003139
Ed Tanousc1e219d2023-06-07 10:34:33 -07003140 asyncResp->res.addHeader(
3141 boost::beast::http::field::link,
3142 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003143
Ed Tanousc1e219d2023-06-07 10:34:33 -07003144 std::optional<bool> locationIndicatorActive;
3145 std::optional<std::string> indicatorLed;
3146 std::optional<std::string> assetTag;
3147 std::optional<std::string> powerRestorePolicy;
3148 std::optional<std::string> powerMode;
3149 std::optional<bool> wdtEnable;
3150 std::optional<std::string> wdtTimeOutAction;
3151 std::optional<std::string> bootSource;
3152 std::optional<std::string> bootType;
3153 std::optional<std::string> bootEnable;
3154 std::optional<std::string> bootAutomaticRetry;
3155 std::optional<uint32_t> bootAutomaticRetryAttempts;
3156 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003157 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003158 std::optional<bool> ipsEnable;
3159 std::optional<uint8_t> ipsEnterUtil;
3160 std::optional<uint64_t> ipsEnterTime;
3161 std::optional<uint8_t> ipsExitUtil;
3162 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003163
Ed Tanousc1e219d2023-06-07 10:34:33 -07003164 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003165 if (!json_util::readJsonPatch(
3166 req, asyncResp->res,
3167 "IndicatorLED", indicatorLed,
3168 "LocationIndicatorActive", locationIndicatorActive,
3169 "AssetTag", assetTag,
3170 "PowerRestorePolicy", powerRestorePolicy,
3171 "PowerMode", powerMode,
3172 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3173 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3174 "Boot/BootSourceOverrideTarget", bootSource,
3175 "Boot/BootSourceOverrideMode", bootType,
3176 "Boot/BootSourceOverrideEnabled", bootEnable,
3177 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003178 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003179 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003180 "Boot/StopBootOnFault", stopBootOnFault,
Ed Tanous22d268c2022-05-19 09:39:07 -07003181 "IdlePowerSaver/Enabled", ipsEnable,
3182 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3183 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3184 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3185 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3186 {
3187 return;
3188 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003189 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003190
Ed Tanousc1e219d2023-06-07 10:34:33 -07003191 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003192
Ed Tanousc1e219d2023-06-07 10:34:33 -07003193 if (assetTag)
3194 {
3195 setAssetTag(asyncResp, *assetTag);
3196 }
James Feistb49ac872019-05-21 15:12:01 -07003197
Ed Tanousc1e219d2023-06-07 10:34:33 -07003198 if (wdtEnable || wdtTimeOutAction)
3199 {
3200 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3201 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003202
Ed Tanousc1e219d2023-06-07 10:34:33 -07003203 if (bootSource || bootType || bootEnable)
3204 {
3205 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3206 }
3207 if (bootAutomaticRetry)
3208 {
3209 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3210 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003211
Ed Tanousc1e219d2023-06-07 10:34:33 -07003212 if (bootAutomaticRetryAttempts)
3213 {
3214 setAutomaticRetryAttempts(asyncResp,
3215 bootAutomaticRetryAttempts.value());
3216 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003217
Ed Tanousc1e219d2023-06-07 10:34:33 -07003218 if (bootTrustedModuleRequired)
3219 {
3220 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3221 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003222
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003223 if (stopBootOnFault)
3224 {
3225 setStopBootOnFault(asyncResp, *stopBootOnFault);
3226 }
3227
Ed Tanousc1e219d2023-06-07 10:34:33 -07003228 if (locationIndicatorActive)
3229 {
George Liu59a17e42022-10-08 09:27:47 +08003230 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003231 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003232
Ed Tanousc1e219d2023-06-07 10:34:33 -07003233 // TODO (Gunnar): Remove IndicatorLED after enough time has
3234 // passed
3235 if (indicatorLed)
3236 {
3237 setIndicatorLedState(asyncResp, *indicatorLed);
3238 asyncResp->res.addHeader(boost::beast::http::field::warning,
3239 "299 - \"IndicatorLED is deprecated. Use "
3240 "LocationIndicatorActive instead.\"");
3241 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003242
Ed Tanousc1e219d2023-06-07 10:34:33 -07003243 if (powerRestorePolicy)
3244 {
3245 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3246 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003247
Ed Tanousc1e219d2023-06-07 10:34:33 -07003248 if (powerMode)
3249 {
3250 setPowerMode(asyncResp, *powerMode);
3251 }
Chris Cain37bbf982021-09-20 10:53:09 -05003252
Ed Tanousc1e219d2023-06-07 10:34:33 -07003253 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3254 {
3255 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3256 ipsExitUtil, ipsExitTime);
3257 }
3258}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303259
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003260inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003261 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003262 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003263 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003264{
3265 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3266 {
3267 return;
3268 }
3269 asyncResp->res.addHeader(
3270 boost::beast::http::field::link,
3271 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3272}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003273
3274/**
3275 * @brief Translates allowed host transitions to redfish string
3276 *
3277 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3278 * @param[out] allowableValues The translated host transition(s)
3279 *
3280 * @return Emplaces correpsonding Redfish translated value(s) in
3281 * allowableValues. If translation not possible, does nothing to
3282 * allowableValues.
3283 */
3284inline void
3285 dbusToRfAllowedHostTransitions(const std::string& dbusAllowedHostTran,
3286 nlohmann::json::array_t& allowableValues)
3287{
3288 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3289 {
3290 allowableValues.emplace_back(resource::ResetType::On);
3291 allowableValues.emplace_back(resource::ResetType::ForceOn);
3292 }
3293 else if (dbusAllowedHostTran ==
3294 "xyz.openbmc_project.State.Host.Transition.Off")
3295 {
3296 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3297 }
3298 else if (dbusAllowedHostTran ==
3299 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3300 {
3301 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3302 }
3303 else if (dbusAllowedHostTran ==
3304 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3305 {
3306 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3307 }
3308 else
3309 {
3310 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3311 }
3312}
3313
3314inline void afterGetAllowedHostTransitions(
3315 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3316 const boost::system::error_code& ec,
3317 const std::vector<std::string>& allowedHostTransitions)
3318{
3319 nlohmann::json::array_t allowableValues;
3320
3321 // Supported on all systems currently
3322 allowableValues.emplace_back(resource::ResetType::ForceOff);
3323 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3324 allowableValues.emplace_back(resource::ResetType::Nmi);
3325
3326 if (ec)
3327 {
Ed Tanouse715d142024-03-07 15:47:37 -08003328 if ((ec.value() ==
3329 boost::system::linux_error::bad_request_descriptor) ||
3330 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003331 {
3332 // Property not implemented so just return defaults
3333 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3334 allowableValues.emplace_back(resource::ResetType::On);
3335 allowableValues.emplace_back(resource::ResetType::ForceOn);
3336 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3337 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3338 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3339 }
3340 else
3341 {
3342 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3343 messages::internalError(asyncResp->res);
3344 return;
3345 }
3346 }
3347 else
3348 {
3349 for (const std::string& transition : allowedHostTransitions)
3350 {
3351 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3352 dbusToRfAllowedHostTransitions(transition, allowableValues);
3353 }
3354 }
3355
3356 nlohmann::json::object_t parameter;
3357 parameter["Name"] = "ResetType";
3358 parameter["Required"] = true;
3359 parameter["DataType"] = "String";
3360 parameter["AllowableValues"] = std::move(allowableValues);
3361 nlohmann::json::array_t parameters;
3362 parameters.emplace_back(std::move(parameter));
3363 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3364}
3365
Ed Tanousc1e219d2023-06-07 10:34:33 -07003366inline void handleSystemCollectionResetActionGet(
3367 crow::App& app, const crow::Request& req,
3368 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3369 const std::string& systemName)
3370{
3371 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3372 {
3373 return;
3374 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003375 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003376 {
3377 // Option currently returns no systems. TBD
3378 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3379 systemName);
3380 return;
3381 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003382
Ed Tanousc1e219d2023-06-07 10:34:33 -07003383 if (systemName == "hypervisor")
3384 {
3385 handleHypervisorResetActionGet(asyncResp);
3386 return;
3387 }
3388
Ed Tanous253f11b2024-05-16 09:38:31 -07003389 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003390 {
3391 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3392 systemName);
3393 return;
3394 }
3395
3396 asyncResp->res.addHeader(
3397 boost::beast::http::field::link,
3398 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3399
3400 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003401 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3402 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003403 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3404 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3405 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3406
Andrew Geissler33e1f122024-02-26 21:10:16 -06003407 // Look to see if system defines AllowedHostTransitions
3408 sdbusplus::asio::getProperty<std::vector<std::string>>(
3409 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
3410 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
3411 "AllowedHostTransitions",
3412 [asyncResp](const boost::system::error_code& ec,
3413 const std::vector<std::string>& allowedHostTransitions) {
3414 afterGetAllowedHostTransitions(asyncResp, ec, allowedHostTransitions);
3415 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003416}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303417/**
3418 * SystemResetActionInfo derived class for delivering Computer Systems
3419 * ResetType AllowableValues using ResetInfo schema.
3420 */
Ed Tanous100afe52023-06-07 13:30:46 -07003421inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303422{
Ed Tanous100afe52023-06-07 13:30:46 -07003423 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3424 .privileges(redfish::privileges::headComputerSystemCollection)
3425 .methods(boost::beast::http::verb::head)(
3426 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3427
3428 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3429 .privileges(redfish::privileges::getComputerSystemCollection)
3430 .methods(boost::beast::http::verb::get)(
3431 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3432
3433 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3434 .privileges(redfish::privileges::headComputerSystem)
3435 .methods(boost::beast::http::verb::head)(
3436 std::bind_front(handleComputerSystemHead, std::ref(app)));
3437
3438 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3439 .privileges(redfish::privileges::getComputerSystem)
3440 .methods(boost::beast::http::verb::get)(
3441 std::bind_front(handleComputerSystemGet, std::ref(app)));
3442
3443 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3444 .privileges(redfish::privileges::patchComputerSystem)
3445 .methods(boost::beast::http::verb::patch)(
3446 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3447
3448 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3449 .privileges(redfish::privileges::postComputerSystem)
3450 .methods(boost::beast::http::verb::post)(std::bind_front(
3451 handleComputerSystemResetActionPost, std::ref(app)));
3452
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003453 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003454 .privileges(redfish::privileges::headActionInfo)
3455 .methods(boost::beast::http::verb::head)(std::bind_front(
3456 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003457 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003458 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003459 .methods(boost::beast::http::verb::get)(std::bind_front(
3460 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003461}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003462} // namespace redfish