blob: 8c4f99129837f35991ba3084d80c3e85884138ed [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 Tanous20fa6a22024-05-20 18:02:58 -070049#include <utility>
Ed Tanousabf2add2019-01-22 16:40:12 -080050#include <variant>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060051#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020052
Ed Tanous1abe55e2018-09-05 08:30:59 -070053namespace redfish
54{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020055
Abhishek Patel5c3e9272021-06-24 10:11:33 -050056const static std::array<std::pair<std::string_view, std::string_view>, 2>
57 protocolToDBusForSystems{
58 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
59
Alpana Kumari9d3ae102019-04-12 06:49:32 -050060/**
61 * @brief Updates the Functional State of DIMMs
62 *
Ed Tanousac106bf2023-06-07 09:24:59 -070063 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050064 * @param[in] dimmState Dimm's Functional state, true/false
65 *
66 * @return None.
67 */
zhanghch058d1b46d2021-04-01 11:18:24 +080068inline void
Ed Tanousac106bf2023-06-07 09:24:59 -070069 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070070 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050071{
Ed Tanous62598e32023-07-17 17:06:25 -070072 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050073
Gunnar Mills4e0453b2020-07-08 14:00:30 -050074 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050075 // Update STATE only if previous State was DISABLED and current Dimm is
76 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070077 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070078 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050079 if (prevMemSummary == "Disabled")
80 {
Ed Tanouse05aec52022-01-25 10:28:56 -080081 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050082 {
Ed Tanousac106bf2023-06-07 09:24:59 -070083 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050084 "Enabled";
85 }
86 }
87}
88
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050089/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050090 * @brief Update "ProcessorSummary" "Status" "State" based on
91 * CPU Functional State
92 *
Ed Tanousac106bf2023-06-07 09:24:59 -070093 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050094 * @param[in] cpuFunctionalState is CPU functional true/false
95 *
96 * @return None.
97 */
Ed Tanousac106bf2023-06-07 09:24:59 -070098inline void modifyCpuFunctionalState(
99 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500100{
Ed Tanous62598e32023-07-17 17:06:25 -0700101 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500102
Ed Tanous02cad962022-06-30 16:50:15 -0700103 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700104 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500105
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500106 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500107 // Update STATE only if previous State was Non_Functional and current CPU is
108 // Functional.
109 if (prevProcState == "Disabled")
110 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800111 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500112 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700113 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114 "Enabled";
115 }
116 }
117}
118
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500119/*
120 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
121 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700122 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500123 * @param[in] cpuPresenceState CPU present or not
124 *
125 * @return None.
126 */
127inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700128 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500129 bool isCpuPresent)
130{
Ed Tanous62598e32023-07-17 17:06:25 -0700131 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500132
133 if (isCpuPresent)
134 {
135 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700136 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500137 auto* procCountPtr =
138 procCount.get_ptr<nlohmann::json::number_integer_t*>();
139 if (procCountPtr != nullptr)
140 {
141 // shouldn't be possible to be nullptr
142 *procCountPtr += 1;
143 }
144 }
145}
146
Ali Ahmed382d6472021-09-03 16:53:53 -0500147inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700148 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500149 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
150 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500151{
Ed Tanous62598e32023-07-17 17:06:25 -0700152 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200154 // TODO: Get Model
155
156 const uint16_t* coreCount = nullptr;
157
158 const bool success = sdbusplus::unpackPropertiesNoThrow(
159 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
160
161 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500162 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700163 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200164 return;
165 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500166
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200167 if (coreCount != nullptr)
168 {
169 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700170 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200171 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500172
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200173 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500174 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200175 coreCountJson = *coreCount;
176 }
177 else
178 {
179 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500180 }
181 }
182}
183
184/*
185 * @brief Get ProcessorSummary fields
186 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700187 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500188 * @param[in] service dbus service for Cpu Information
189 * @param[in] path dbus path for Cpu
190 *
191 * @return None.
192 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700193inline void
194 getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
195 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500196{
Ed Tanousac106bf2023-06-07 09:24:59 -0700197 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
198 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500199 if (ec3)
200 {
Ed Tanous62598e32023-07-17 17:06:25 -0700201 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500202 return;
203 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700204 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500205 };
206
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500207 // Get the Presence of CPU
208 sdbusplus::asio::getProperty<bool>(
209 *crow::connections::systemBus, service, path,
210 "xyz.openbmc_project.Inventory.Item", "Present",
211 std::move(getCpuPresenceState));
212
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200213 sdbusplus::asio::getAllProperties(
214 *crow::connections::systemBus, service, path,
215 "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700216 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800217 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800218 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700219 if (ec2)
220 {
Ed Tanous62598e32023-07-17 17:06:25 -0700221 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700222 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700223 return;
224 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700225 getProcessorProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500226 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500227}
228
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500229/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500230 * @brief processMemoryProperties fields
231 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700232 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500233 * @param[in] DBUS properties for memory
234 *
235 * @return None.
236 */
237inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700238 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500239 const dbus::utility::DBusPropertiesMap& properties)
240{
Ed Tanous62598e32023-07-17 17:06:25 -0700241 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500242
243 if (properties.empty())
244 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500245 return;
246 }
247
248 const size_t* memorySizeInKB = nullptr;
249
250 const bool success = sdbusplus::unpackPropertiesNoThrow(
251 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
252 memorySizeInKB);
253
254 if (!success)
255 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700256 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500257 return;
258 }
259
260 if (memorySizeInKB != nullptr)
261 {
262 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700263 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500264 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500265 if (preValue == nullptr)
266 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700267 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500268 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500269 }
270 else
271 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700272 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500273 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
274 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500275 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500276 }
277}
278
279/*
280 * @brief Get getMemorySummary fields
281 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700282 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500283 * @param[in] service dbus service for memory Information
284 * @param[in] path dbus path for memory
285 *
286 * @return None.
287 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700288inline void
289 getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
290 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500291{
292 sdbusplus::asio::getAllProperties(
293 *crow::connections::systemBus, service, path,
294 "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700295 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500296 path](const boost::system::error_code& ec2,
297 const dbus::utility::DBusPropertiesMap& properties) {
298 if (ec2)
299 {
Ed Tanous62598e32023-07-17 17:06:25 -0700300 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700301 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500302 return;
303 }
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500304 processMemoryProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500305 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500306}
307
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500308inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
309 const boost::system::error_code& ec,
310 const dbus::utility::DBusPropertiesMap& properties)
311{
312 if (ec)
313 {
314 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
315 messages::internalError(asyncResp->res);
316 return;
317 }
318 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
319
320 const std::string* uUID = nullptr;
321
322 const bool success = sdbusplus::unpackPropertiesNoThrow(
323 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
324
325 if (!success)
326 {
327 messages::internalError(asyncResp->res);
328 return;
329 }
330
331 if (uUID != nullptr)
332 {
333 std::string valueStr = *uUID;
334 if (valueStr.size() == 32)
335 {
336 valueStr.insert(8, 1, '-');
337 valueStr.insert(13, 1, '-');
338 valueStr.insert(18, 1, '-');
339 valueStr.insert(23, 1, '-');
340 }
341 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
342 asyncResp->res.jsonValue["UUID"] = valueStr;
343 }
344}
345
346inline void
347 afterGetInventory(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
348 const boost::system::error_code& ec,
349 const dbus::utility::DBusPropertiesMap& propertiesList)
350{
351 if (ec)
352 {
353 // doesn't have to include this
354 // interface
355 return;
356 }
357 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
358
359 const std::string* partNumber = nullptr;
360 const std::string* serialNumber = nullptr;
361 const std::string* manufacturer = nullptr;
362 const std::string* model = nullptr;
363 const std::string* subModel = nullptr;
364
365 const bool success = sdbusplus::unpackPropertiesNoThrow(
366 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
367 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
368 "Model", model, "SubModel", subModel);
369
370 if (!success)
371 {
372 messages::internalError(asyncResp->res);
373 return;
374 }
375
376 if (partNumber != nullptr)
377 {
378 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
379 }
380
381 if (serialNumber != nullptr)
382 {
383 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
384 }
385
386 if (manufacturer != nullptr)
387 {
388 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
389 }
390
391 if (model != nullptr)
392 {
393 asyncResp->res.jsonValue["Model"] = *model;
394 }
395
396 if (subModel != nullptr)
397 {
398 asyncResp->res.jsonValue["SubModel"] = *subModel;
399 }
400
401 // Grab the bios version
402 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
403 "BiosVersion", false);
404}
405
406inline void
407 afterGetAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
408 const boost::system::error_code& ec,
409 const std::string& value)
410{
411 if (ec)
412 {
413 // doesn't have to include this
414 // interface
415 return;
416 }
417
418 asyncResp->res.jsonValue["AssetTag"] = value;
419}
420
421inline void afterSystemGetSubTree(
422 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500423 const boost::system::error_code& ec,
424 const dbus::utility::MapperGetSubTreeResponse& subtree)
425{
426 if (ec)
427 {
428 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
429 messages::internalError(asyncResp->res);
430 return;
431 }
432 // Iterate over all retrieved ObjectPaths.
433 for (const std::pair<
434 std::string,
435 std::vector<std::pair<std::string, std::vector<std::string>>>>&
436 object : subtree)
437 {
438 const std::string& path = object.first;
439 BMCWEB_LOG_DEBUG("Got path: {}", path);
440 const std::vector<std::pair<std::string, std::vector<std::string>>>&
441 connectionNames = object.second;
442 if (connectionNames.empty())
443 {
444 continue;
445 }
446
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500447 // This is not system, so check if it's cpu, dimm, UUID or
448 // BiosVer
449 for (const auto& connection : connectionNames)
450 {
451 for (const auto& interfaceName : connection.second)
452 {
453 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
454 {
455 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
456
457 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500458 }
459 else if (interfaceName ==
460 "xyz.openbmc_project.Inventory.Item.Cpu")
461 {
462 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
463
464 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500465 }
466 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
467 {
468 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
469
470 sdbusplus::asio::getAllProperties(
471 *crow::connections::systemBus, connection.first, path,
472 "xyz.openbmc_project.Common.UUID",
473 [asyncResp](const boost::system::error_code& ec3,
474 const dbus::utility::DBusPropertiesMap&
475 properties) {
476 afterGetUUID(asyncResp, ec3, properties);
477 });
478 }
479 else if (interfaceName ==
480 "xyz.openbmc_project.Inventory.Item.System")
481 {
482 sdbusplus::asio::getAllProperties(
483 *crow::connections::systemBus, connection.first, path,
484 "xyz.openbmc_project.Inventory.Decorator.Asset",
485 [asyncResp](const boost::system::error_code& ec3,
486 const dbus::utility::DBusPropertiesMap&
487 properties) {
488 afterGetInventory(asyncResp, ec3, properties);
489 });
490
491 sdbusplus::asio::getProperty<std::string>(
492 *crow::connections::systemBus, connection.first, path,
493 "xyz.openbmc_project.Inventory.Decorator."
494 "AssetTag",
495 "AssetTag",
496 std::bind_front(afterGetAssetTag, asyncResp));
497 }
498 }
499 }
500 }
501}
502
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500503/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700504 * @brief Retrieves computer system properties over dbus
505 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700506 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700507 *
508 * @return None.
509 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700510inline void
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500511 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700512{
Ed Tanous62598e32023-07-17 17:06:25 -0700513 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800514 constexpr std::array<std::string_view, 5> interfaces = {
515 "xyz.openbmc_project.Inventory.Decorator.Asset",
516 "xyz.openbmc_project.Inventory.Item.Cpu",
517 "xyz.openbmc_project.Inventory.Item.Dimm",
518 "xyz.openbmc_project.Inventory.Item.System",
519 "xyz.openbmc_project.Common.UUID",
520 };
521 dbus::utility::getSubTree(
522 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500523 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700524}
525
526/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700527 * @brief Retrieves host state properties over dbus
528 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700529 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Ed Tanous6c34de42018-08-29 13:37:36 -0700530 *
531 * @return None.
532 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700533inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700534{
Ed Tanous62598e32023-07-17 17:06:25 -0700535 BMCWEB_LOG_DEBUG("Get host information.");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700536 sdbusplus::asio::getProperty<std::string>(
537 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
538 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
539 "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700540 [asyncResp](const boost::system::error_code& ec,
541 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700542 if (ec)
543 {
544 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700545 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700546 // Service not available, no error, just don't return
547 // host state info
Ed Tanous62598e32023-07-17 17:06:25 -0700548 BMCWEB_LOG_DEBUG("Service not available {}", ec);
Ed Tanous6c34de42018-08-29 13:37:36 -0700549 return;
550 }
Ed Tanous62598e32023-07-17 17:06:25 -0700551 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700552 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700553 return;
554 }
Ed Tanous66173382018-08-15 18:20:59 -0700555
Ed Tanous62598e32023-07-17 17:06:25 -0700556 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
Ed Tanous002d39b2022-05-31 08:59:27 -0700557 // Verify Host State
558 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
559 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700560 asyncResp->res.jsonValue["PowerState"] = "On";
561 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700562 }
563 else if (hostState ==
564 "xyz.openbmc_project.State.Host.HostState.Quiesced")
565 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700566 asyncResp->res.jsonValue["PowerState"] = "On";
567 asyncResp->res.jsonValue["Status"]["State"] = "Quiesced";
Ed Tanous002d39b2022-05-31 08:59:27 -0700568 }
569 else if (hostState ==
570 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
571 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700572 asyncResp->res.jsonValue["PowerState"] = "On";
573 asyncResp->res.jsonValue["Status"]["State"] = "InTest";
Ed Tanous002d39b2022-05-31 08:59:27 -0700574 }
575 else if (
576 hostState ==
577 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
578 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700579 asyncResp->res.jsonValue["PowerState"] = "PoweringOn";
580 asyncResp->res.jsonValue["Status"]["State"] = "Starting";
Ed Tanous002d39b2022-05-31 08:59:27 -0700581 }
582 else if (hostState ==
583 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
584 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700585 asyncResp->res.jsonValue["PowerState"] = "PoweringOff";
586 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700587 }
588 else
589 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700590 asyncResp->res.jsonValue["PowerState"] = "Off";
591 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -0700592 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500593 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700594}
595
596/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500597 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530598 *
599 * @param[in] dbusSource The boot source in DBUS speak.
600 *
601 * @return Returns as a string, the boot source in Redfish terms. If translation
602 * cannot be done, returns an empty string.
603 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000604inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530605{
606 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
607 {
608 return "None";
609 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700610 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530611 {
612 return "Hdd";
613 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700614 if (dbusSource ==
615 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530616 {
617 return "Cd";
618 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700619 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530620 {
621 return "Pxe";
622 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700623 if (dbusSource ==
624 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700625 {
626 return "Usb";
627 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700628 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530629}
630
631/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300632 * @brief Translates boot type DBUS property value to redfish.
633 *
634 * @param[in] dbusType The boot type in DBUS speak.
635 *
636 * @return Returns as a string, the boot type in Redfish terms. If translation
637 * cannot be done, returns an empty string.
638 */
639inline std::string dbusToRfBootType(const std::string& dbusType)
640{
641 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
642 {
643 return "Legacy";
644 }
645 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
646 {
647 return "UEFI";
648 }
649 return "";
650}
651
652/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500653 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530654 *
655 * @param[in] dbusMode The boot mode in DBUS speak.
656 *
657 * @return Returns as a string, the boot mode in Redfish terms. If translation
658 * cannot be done, returns an empty string.
659 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000660inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661{
662 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
663 {
664 return "None";
665 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700666 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530667 {
668 return "Diags";
669 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700670 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530671 {
672 return "BiosSetup";
673 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700674 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530675}
676
677/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600678 * @brief Translates boot progress DBUS property value to redfish.
679 *
680 * @param[in] dbusBootProgress The boot progress in DBUS speak.
681 *
682 * @return Returns as a string, the boot progress in Redfish terms. If
683 * translation cannot be done, returns "None".
684 */
685inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
686{
687 // Now convert the D-Bus BootProgress to the appropriate Redfish
688 // enum
689 std::string rfBpLastState = "None";
690 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
691 "ProgressStages.Unspecified")
692 {
693 rfBpLastState = "None";
694 }
695 else if (dbusBootProgress ==
696 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
697 "PrimaryProcInit")
698 {
699 rfBpLastState = "PrimaryProcessorInitializationStarted";
700 }
701 else if (dbusBootProgress ==
702 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
703 "BusInit")
704 {
705 rfBpLastState = "BusInitializationStarted";
706 }
707 else if (dbusBootProgress ==
708 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
709 "MemoryInit")
710 {
711 rfBpLastState = "MemoryInitializationStarted";
712 }
713 else if (dbusBootProgress ==
714 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
715 "SecondaryProcInit")
716 {
717 rfBpLastState = "SecondaryProcessorInitializationStarted";
718 }
719 else if (dbusBootProgress ==
720 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
721 "PCIInit")
722 {
723 rfBpLastState = "PCIResourceConfigStarted";
724 }
725 else if (dbusBootProgress ==
726 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
727 "SystemSetup")
728 {
729 rfBpLastState = "SetupEntered";
730 }
731 else if (dbusBootProgress ==
732 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
733 "SystemInitComplete")
734 {
735 rfBpLastState = "SystemHardwareInitializationComplete";
736 }
737 else if (dbusBootProgress ==
738 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
739 "OSStart")
740 {
741 rfBpLastState = "OSBootStarted";
742 }
743 else if (dbusBootProgress ==
744 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
745 "OSRunning")
746 {
747 rfBpLastState = "OSRunning";
748 }
749 else
750 {
Ed Tanous62598e32023-07-17 17:06:25 -0700751 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600752 // Just return the default
753 }
754 return rfBpLastState;
755}
756
757/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500758 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530759 *
760 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700761 * @param[out] bootSource The DBus source
762 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530763 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700764 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530765 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700766inline int
767 assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
768 const std::string& rfSource, std::string& bootSource,
769 std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530770{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300771 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
772 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700773
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 if (rfSource == "None")
775 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700778 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530779 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
781 }
782 else if (rfSource == "Hdd")
783 {
784 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
785 }
786 else if (rfSource == "Diags")
787 {
788 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
789 }
790 else if (rfSource == "Cd")
791 {
792 bootSource =
793 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
794 }
795 else if (rfSource == "BiosSetup")
796 {
797 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530798 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700799 else if (rfSource == "Usb")
800 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700801 bootSource =
802 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700803 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530804 else
805 {
Ed Tanous62598e32023-07-17 17:06:25 -0700806 BMCWEB_LOG_DEBUG(
807 "Invalid property value for BootSourceOverrideTarget: {}",
808 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700809 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700810 "BootSourceTargetOverride");
811 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530812 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700813 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530814}
Ali Ahmed19817712021-06-29 17:01:52 -0500815
Andrew Geissler978b8802020-11-19 13:36:40 -0600816/**
817 * @brief Retrieves boot progress of the system
818 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700819 * @param[in] asyncResp Shared pointer for generating response message.
Andrew Geissler978b8802020-11-19 13:36:40 -0600820 *
821 * @return None.
822 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700823inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600824{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700825 sdbusplus::asio::getProperty<std::string>(
826 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
827 "/xyz/openbmc_project/state/host0",
828 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700829 [asyncResp](const boost::system::error_code& ec,
830 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700831 if (ec)
832 {
833 // BootProgress is an optional object so just do nothing if
834 // not found
835 return;
836 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600837
Ed Tanous62598e32023-07-17 17:06:25 -0700838 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600839
Ed Tanousac106bf2023-06-07 09:24:59 -0700840 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700841 dbusToRfBootProgress(bootProgressStr);
Patrick Williams5a39f772023-10-20 11:20:21 -0500842 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600843}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530844
845/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000846 * @brief Retrieves boot progress Last Update of the system
847 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700848 * @param[in] asyncResp Shared pointer for generating response message.
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000849 *
850 * @return None.
851 */
852inline void getBootProgressLastStateTime(
Ed Tanousac106bf2023-06-07 09:24:59 -0700853 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000854{
855 sdbusplus::asio::getProperty<uint64_t>(
856 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
857 "/xyz/openbmc_project/state/host0",
858 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700859 [asyncResp](const boost::system::error_code& ec,
860 const uint64_t lastStateTime) {
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000861 if (ec)
862 {
Ed Tanous62598e32023-07-17 17:06:25 -0700863 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000864 return;
865 }
866
867 // BootProgressLastUpdate is the last time the BootProgress property
868 // was updated. The time is the Epoch time, number of microseconds
869 // since 1 Jan 1970 00::00::00 UTC."
870 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
871 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
872
873 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -0700874 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000875 redfish::time_utils::getDateTimeUintUs(lastStateTime);
Patrick Williams5a39f772023-10-20 11:20:21 -0500876 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000877}
878
879/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300880 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300881 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700882 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300883 *
884 * @return None.
885 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300886
Ed Tanousac106bf2023-06-07 09:24:59 -0700887inline void
888 getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300889{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700890 sdbusplus::asio::getProperty<std::string>(
891 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
892 "/xyz/openbmc_project/control/host0/boot",
893 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700894 [asyncResp](const boost::system::error_code& ec,
895 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700896 if (ec)
897 {
898 // not an error, don't have to have the interface
899 return;
900 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300901
Ed Tanous62598e32023-07-17 17:06:25 -0700902 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300903
Ed Tanousac106bf2023-06-07 09:24:59 -0700904 asyncResp->res
905 .jsonValue["Boot"]
906 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700907 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300908
Ed Tanous002d39b2022-05-31 08:59:27 -0700909 auto rfType = dbusToRfBootType(bootType);
910 if (rfType.empty())
911 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700912 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700913 return;
914 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300915
Ed Tanousac106bf2023-06-07 09:24:59 -0700916 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Patrick Williams5a39f772023-10-20 11:20:21 -0500917 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918}
919
920/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300921 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530922 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700923 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530924 *
925 * @return None.
926 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300927
Ed Tanousac106bf2023-06-07 09:24:59 -0700928inline void
929 getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530930{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700931 sdbusplus::asio::getProperty<std::string>(
932 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
933 "/xyz/openbmc_project/control/host0/boot",
934 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700935 [asyncResp](const boost::system::error_code& ec,
936 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700937 if (ec)
938 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -0500939 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700940 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700941 return;
942 }
943
Ed Tanous62598e32023-07-17 17:06:25 -0700944 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
Ed Tanous002d39b2022-05-31 08:59:27 -0700945
Ed Tanous20fa6a22024-05-20 18:02:58 -0700946 nlohmann::json::array_t allowed;
947 allowed.emplace_back("None");
948 allowed.emplace_back("Pxe");
949 allowed.emplace_back("Hdd");
950 allowed.emplace_back("Cd");
951 allowed.emplace_back("Diags");
952 allowed.emplace_back("BiosSetup");
953 allowed.emplace_back("Usb");
954
Ed Tanousac106bf2023-06-07 09:24:59 -0700955 asyncResp->res
Ed Tanous002d39b2022-05-31 08:59:27 -0700956 .jsonValue["Boot"]
Ed Tanous20fa6a22024-05-20 18:02:58 -0700957 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
958 std::move(allowed);
Ed Tanous002d39b2022-05-31 08:59:27 -0700959 if (bootModeStr !=
960 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
961 {
962 auto rfMode = dbusToRfBootMode(bootModeStr);
963 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530964 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700965 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700966 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700968 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500969 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530970}
971
972/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300973 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700975 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530976 *
977 * @return None.
978 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300979
980inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700981 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530982{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700983 sdbusplus::asio::getProperty<std::string>(
984 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
985 "/xyz/openbmc_project/control/host0/boot",
986 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanousac106bf2023-06-07 09:24:59 -0700987 [asyncResp](const boost::system::error_code& ec,
988 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700989 if (ec)
990 {
Nan Zhou5ef735c2022-06-22 05:24:21 +0000991 if (ec.value() == boost::asio::error::host_unreachable)
992 {
993 return;
994 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -0500995 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700996 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700997 return;
998 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530999
Ed Tanous62598e32023-07-17 17:06:25 -07001000 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301001
Ed Tanous002d39b2022-05-31 08:59:27 -07001002 auto rfSource = dbusToRfBootSource(bootSourceStr);
1003 if (!rfSource.empty())
1004 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001005 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1006 rfSource;
Ed Tanous002d39b2022-05-31 08:59:27 -07001007 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001008
Ed Tanous002d39b2022-05-31 08:59:27 -07001009 // Get BootMode as BootSourceOverrideTarget is constructed
1010 // from both BootSource and BootMode
Ed Tanousac106bf2023-06-07 09:24:59 -07001011 getBootOverrideMode(asyncResp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001012 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301013}
1014
1015/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001016 * @brief This functions abstracts all the logic behind getting a
1017 * "BootSourceOverrideEnabled" property from an overall boot override enable
1018 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001020 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301021 *
1022 * @return None.
1023 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301024
Ed Tanousac106bf2023-06-07 09:24:59 -07001025inline void processBootOverrideEnable(
1026 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1027 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001028{
1029 if (!bootOverrideEnableSetting)
1030 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001031 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1032 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001033 return;
1034 }
1035
1036 // If boot source override is enabled, we need to check 'one_time'
1037 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001038 sdbusplus::asio::getProperty<bool>(
1039 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1040 "/xyz/openbmc_project/control/host0/boot/one_time",
1041 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001042 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001043 if (ec)
1044 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001045 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001046 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001047 return;
1048 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301049
Ed Tanous002d39b2022-05-31 08:59:27 -07001050 if (oneTimeSetting)
1051 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001052 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1053 "Once";
Ed Tanous002d39b2022-05-31 08:59:27 -07001054 }
1055 else
1056 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001057 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001058 "Continuous";
1059 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001060 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301061}
1062
1063/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001064 * @brief Retrieves boot override enable over DBUS
1065 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001066 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001067 *
1068 * @return None.
1069 */
1070
1071inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001072 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001073{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001074 sdbusplus::asio::getProperty<bool>(
1075 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1076 "/xyz/openbmc_project/control/host0/boot",
1077 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001078 [asyncResp](const boost::system::error_code& ec,
1079 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001080 if (ec)
1081 {
Nan Zhou5ef735c2022-06-22 05:24:21 +00001082 if (ec.value() == boost::asio::error::host_unreachable)
1083 {
1084 return;
1085 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001086 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001087 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001088 return;
1089 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001090
Ed Tanousac106bf2023-06-07 09:24:59 -07001091 processBootOverrideEnable(asyncResp, bootOverrideEnable);
Patrick Williams5a39f772023-10-20 11:20:21 -05001092 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001093}
1094
1095/**
1096 * @brief Retrieves boot source override properties
1097 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001098 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001099 *
1100 * @return None.
1101 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001102inline void
1103 getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001104{
Ed Tanous62598e32023-07-17 17:06:25 -07001105 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001106
Ed Tanousac106bf2023-06-07 09:24:59 -07001107 getBootOverrideSource(asyncResp);
1108 getBootOverrideType(asyncResp);
1109 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001110}
1111
1112/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001113 * @brief Retrieves the Last Reset Time
1114 *
1115 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1116 * and power off. Even though this is the "system" Redfish object look at the
1117 * chassis D-Bus interface for the LastStateChangeTime since this has the
1118 * last power operation time.
1119 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001120 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001121 *
1122 * @return None.
1123 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001124inline void
1125 getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001126{
Ed Tanous62598e32023-07-17 17:06:25 -07001127 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001128
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001129 sdbusplus::asio::getProperty<uint64_t>(
1130 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1131 "/xyz/openbmc_project/state/chassis0",
1132 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001133 [asyncResp](const boost::system::error_code& ec,
1134 uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001135 if (ec)
1136 {
Ed Tanous62598e32023-07-17 17:06:25 -07001137 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001138 return;
1139 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001140
Ed Tanous002d39b2022-05-31 08:59:27 -07001141 // LastStateChangeTime is epoch time, in milliseconds
1142 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1143 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001144
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -07001146 asyncResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001147 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001148 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001149}
1150
1151/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001152 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1153 *
1154 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1155 * corresponding property "AttemptsLeft" that keeps track of the amount of
1156 * automatic retry attempts left are hosted in phosphor-state-manager through
1157 * dbus.
1158 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001159 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001160 *
1161 * @return None.
1162 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001163inline void getAutomaticRebootAttempts(
1164 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001165{
Ed Tanous62598e32023-07-17 17:06:25 -07001166 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001167
1168 sdbusplus::asio::getAllProperties(
1169 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1170 "/xyz/openbmc_project/state/host0",
1171 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001172 [asyncResp{asyncResp}](
1173 const boost::system::error_code& ec,
1174 const dbus::utility::DBusPropertiesMap& propertiesList) {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001175 if (ec)
1176 {
1177 if (ec.value() != EBADR)
1178 {
Ed Tanous62598e32023-07-17 17:06:25 -07001179 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001180 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001181 }
1182 return;
1183 }
1184
1185 const uint32_t* attemptsLeft = nullptr;
1186 const uint32_t* retryAttempts = nullptr;
1187
1188 const bool success = sdbusplus::unpackPropertiesNoThrow(
1189 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1190 attemptsLeft, "RetryAttempts", retryAttempts);
1191
1192 if (!success)
1193 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001194 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001195 return;
1196 }
1197
1198 if (attemptsLeft != nullptr)
1199 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001200 asyncResp->res
1201 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001202 *attemptsLeft;
1203 }
1204
1205 if (retryAttempts != nullptr)
1206 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001207 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001208 *retryAttempts;
1209 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001210 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001211}
1212
1213/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001214 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1215 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001216 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001217 *
1218 * @return None.
1219 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001220inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001221 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001222{
Ed Tanous62598e32023-07-17 17:06:25 -07001223 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001224
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001225 sdbusplus::asio::getProperty<bool>(
1226 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1227 "/xyz/openbmc_project/control/host0/auto_reboot",
1228 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001229 [asyncResp](const boost::system::error_code& ec,
1230 bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001231 if (ec)
1232 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001233 if (ec.value() != EBADR)
1234 {
Ed Tanous62598e32023-07-17 17:06:25 -07001235 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001236 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001237 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001238 return;
1239 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001240
Ed Tanous62598e32023-07-17 17:06:25 -07001241 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
Ed Tanous002d39b2022-05-31 08:59:27 -07001242 if (autoRebootEnabled)
1243 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001244 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001245 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001246 }
1247 else
1248 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001249 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1250 "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -07001251 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001252 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001253
Ed Tanous002d39b2022-05-31 08:59:27 -07001254 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1255 // and RetryAttempts. OpenBMC only supports Disabled and
1256 // RetryAttempts.
Ed Tanous20fa6a22024-05-20 18:02:58 -07001257 nlohmann::json::array_t allowed;
1258 allowed.emplace_back("Disabled");
1259 allowed.emplace_back("RetryAttempts");
Ed Tanousac106bf2023-06-07 09:24:59 -07001260 asyncResp->res
1261 .jsonValue["Boot"]["AutomaticRetryConfig@Redfish.AllowableValues"] =
Ed Tanous20fa6a22024-05-20 18:02:58 -07001262 std::move(allowed);
Patrick Williams5a39f772023-10-20 11:20:21 -05001263 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001264}
1265
1266/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001267 * @brief Sets RetryAttempts
1268 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001269 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001270 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1271 *
1272 *@return None.
1273 */
1274
Ed Tanousac106bf2023-06-07 09:24:59 -07001275inline void setAutomaticRetryAttempts(
1276 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1277 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001278{
Ed Tanous62598e32023-07-17 17:06:25 -07001279 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001280 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301281 asyncResp, "Boot/AutomaticRetryAttempts",
1282 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001283 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001284 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301285 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001286}
1287
Ed Tanous8d69c662023-06-21 10:29:06 -07001288inline computer_system::PowerRestorePolicyTypes
1289 redfishPowerRestorePolicyFromDbus(std::string_view value)
1290{
1291 if (value ==
1292 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1293 {
1294 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1295 }
1296 if (value ==
1297 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1298 {
1299 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1300 }
1301 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001302 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001303 {
1304 return computer_system::PowerRestorePolicyTypes::LastState;
1305 }
1306 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1307 {
1308 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1309 }
1310 return computer_system::PowerRestorePolicyTypes::Invalid;
1311}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001312/**
George Liuc6a620f2020-04-10 17:18:11 +08001313 * @brief Retrieves power restore policy over DBUS.
1314 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001315 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001316 *
1317 * @return None.
1318 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001319inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001320 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001321{
Ed Tanous62598e32023-07-17 17:06:25 -07001322 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001323
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001324 sdbusplus::asio::getProperty<std::string>(
1325 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1326 "/xyz/openbmc_project/control/host0/power_restore_policy",
1327 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001328 [asyncResp](const boost::system::error_code& ec,
1329 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001330 if (ec)
1331 {
Ed Tanous62598e32023-07-17 17:06:25 -07001332 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001333 return;
1334 }
Ed Tanous8d69c662023-06-21 10:29:06 -07001335 computer_system::PowerRestorePolicyTypes restore =
1336 redfishPowerRestorePolicyFromDbus(policy);
1337 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -07001338 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001339 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001340 return;
1341 }
George Liuc6a620f2020-04-10 17:18:11 +08001342
Ed Tanous8d69c662023-06-21 10:29:06 -07001343 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
Patrick Williams5a39f772023-10-20 11:20:21 -05001344 });
George Liuc6a620f2020-04-10 17:18:11 +08001345}
1346
1347/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001348 * @brief Stop Boot On Fault over DBUS.
1349 *
1350 * @param[in] asyncResp Shared pointer for generating response message.
1351 *
1352 * @return None.
1353 */
1354inline void
1355 getStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1356{
Ed Tanous62598e32023-07-17 17:06:25 -07001357 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001358
1359 sdbusplus::asio::getProperty<bool>(
1360 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1361 "/xyz/openbmc_project/logging/settings",
1362 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1363 [asyncResp](const boost::system::error_code& ec, bool value) {
1364 if (ec)
1365 {
1366 if (ec.value() != EBADR)
1367 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001368 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001369 messages::internalError(asyncResp->res);
1370 }
1371 return;
1372 }
1373
1374 if (value)
1375 {
1376 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "AnyFault";
1377 }
1378 else
1379 {
1380 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "Never";
1381 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001382 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001383}
1384
1385/**
Ali Ahmed19817712021-06-29 17:01:52 -05001386 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1387 * TPM is required for booting the host.
1388 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001389 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001390 *
1391 * @return None.
1392 */
1393inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001394 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001395{
Ed Tanous62598e32023-07-17 17:06:25 -07001396 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001397 constexpr std::array<std::string_view, 1> interfaces = {
1398 "xyz.openbmc_project.Control.TPM.Policy"};
1399 dbus::utility::getSubTree(
1400 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001401 [asyncResp](const boost::system::error_code& ec,
1402 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001403 if (ec)
1404 {
Ed Tanous62598e32023-07-17 17:06:25 -07001405 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}",
1406 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001407 // This is an optional D-Bus object so just return if
1408 // error occurs
1409 return;
1410 }
1411 if (subtree.empty())
1412 {
1413 // As noted above, this is an optional interface so just return
1414 // if there is no instance found
1415 return;
1416 }
1417
1418 /* When there is more than one TPMEnable object... */
1419 if (subtree.size() > 1)
1420 {
Ed Tanous62598e32023-07-17 17:06:25 -07001421 BMCWEB_LOG_DEBUG(
1422 "DBUS response has more than 1 TPM Enable object:{}",
1423 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001424 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001425 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001426 return;
1427 }
1428
1429 // Make sure the Dbus response map has a service and objectPath
1430 // field
1431 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1432 {
Ed Tanous62598e32023-07-17 17:06:25 -07001433 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001434 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001435 return;
1436 }
1437
1438 const std::string& path = subtree[0].first;
1439 const std::string& serv = subtree[0].second.begin()->first;
1440
1441 // Valid TPM Enable object found, now reading the current value
1442 sdbusplus::asio::getProperty<bool>(
1443 *crow::connections::systemBus, serv, path,
1444 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanousac106bf2023-06-07 09:24:59 -07001445 [asyncResp](const boost::system::error_code& ec2,
1446 bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001447 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001448 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001449 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001450 ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001451 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001452 return;
1453 }
1454
Ed Tanous002d39b2022-05-31 08:59:27 -07001455 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001456 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001457 asyncResp->res
1458 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001459 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001460 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001461 else
1462 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001463 asyncResp->res
1464 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001465 "Disabled";
1466 }
George Liue99073f2022-12-09 11:06:16 +08001467 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001468 });
Ali Ahmed19817712021-06-29 17:01:52 -05001469}
1470
1471/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001472 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1473 * TPM is required for booting the host.
1474 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001475 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001476 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1477 *
1478 * @return None.
1479 */
1480inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001481 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001482{
Ed Tanous62598e32023-07-17 17:06:25 -07001483 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001484 constexpr std::array<std::string_view, 1> interfaces = {
1485 "xyz.openbmc_project.Control.TPM.Policy"};
1486 dbus::utility::getSubTree(
1487 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001488 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001489 tpmRequired](const boost::system::error_code& ec,
1490 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001491 if (ec)
1492 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001493 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001494 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001495 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001496 return;
1497 }
1498 if (subtree.empty())
1499 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001500 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07001501 "TrustedModuleRequiredToBoot");
1502 return;
1503 }
1504
1505 /* When there is more than one TPMEnable object... */
1506 if (subtree.size() > 1)
1507 {
Ed Tanous62598e32023-07-17 17:06:25 -07001508 BMCWEB_LOG_DEBUG(
1509 "DBUS response has more than 1 TPM Enable object:{}",
1510 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001511 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001512 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001513 return;
1514 }
1515
1516 // Make sure the Dbus response map has a service and objectPath
1517 // field
1518 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1519 {
Ed Tanous62598e32023-07-17 17:06:25 -07001520 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001521 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001522 return;
1523 }
1524
1525 const std::string& path = subtree[0].first;
1526 const std::string& serv = subtree[0].second.begin()->first;
1527
1528 if (serv.empty())
1529 {
Ed Tanous62598e32023-07-17 17:06:25 -07001530 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001531 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001532 return;
1533 }
1534
1535 // Valid TPM Enable object found, now setting the value
Ginu Georgee93abac2024-06-14 17:35:27 +05301536 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1537 path, "xyz.openbmc_project.Control.TPM.Policy",
1538 "TPMEnable", tpmRequired);
Patrick Williams5a39f772023-10-20 11:20:21 -05001539 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001540}
1541
1542/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301543 * @brief Sets boot properties into DBUS object(s).
1544 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001545 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001546 * @param[in] bootType The boot type to set.
1547 * @return Integer error code.
1548 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001549inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001550 const std::optional<std::string>& bootType)
1551{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001552 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001553
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001554 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001555 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001556 return;
1557 }
1558
1559 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001560 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001561 // Figure out which DBUS interface and property to use
1562 if (*bootType == "Legacy")
1563 {
1564 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1565 }
1566 else if (*bootType == "UEFI")
1567 {
1568 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1569 }
1570 else
1571 {
Ed Tanous62598e32023-07-17 17:06:25 -07001572 BMCWEB_LOG_DEBUG("Invalid property value for "
1573 "BootSourceOverrideMode: {}",
1574 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001575 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001576 "BootSourceOverrideMode");
1577 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001578 }
1579
1580 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001581 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001582
Ginu Georgee93abac2024-06-14 17:35:27 +05301583 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1584 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001585 sdbusplus::message::object_path(
1586 "/xyz/openbmc_project/control/host0/boot"),
1587 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301588 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001589}
1590
1591/**
1592 * @brief Sets boot properties into DBUS object(s).
1593 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001594 * @param[in] asyncResp Shared pointer for generating response
1595 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001596 * @param[in] bootType The boot type to set.
1597 * @return Integer error code.
1598 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001599inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001600 const std::optional<std::string>& bootEnable)
1601{
1602 if (!bootEnable)
1603 {
1604 return;
1605 }
1606 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001607 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001608
1609 bool bootOverrideEnable = false;
1610 bool bootOverridePersistent = false;
1611 // Figure out which DBUS interface and property to use
1612 if (*bootEnable == "Disabled")
1613 {
1614 bootOverrideEnable = false;
1615 }
1616 else if (*bootEnable == "Once")
1617 {
1618 bootOverrideEnable = true;
1619 bootOverridePersistent = false;
1620 }
1621 else if (*bootEnable == "Continuous")
1622 {
1623 bootOverrideEnable = true;
1624 bootOverridePersistent = true;
1625 }
1626 else
1627 {
Ed Tanous62598e32023-07-17 17:06:25 -07001628 BMCWEB_LOG_DEBUG(
1629 "Invalid property value for BootSourceOverrideEnabled: {}",
1630 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001631 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001632 "BootSourceOverrideEnabled");
1633 return;
1634 }
1635
1636 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001637 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001638
Ginu Georgee93abac2024-06-14 17:35:27 +05301639 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1640 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001641 sdbusplus::message::object_path(
1642 "/xyz/openbmc_project/control/host0/boot"),
1643 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301644 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001645
1646 if (!bootOverrideEnable)
1647 {
1648 return;
1649 }
1650
1651 // In case boot override is enabled we need to set correct value for the
1652 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001653 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1654 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001655
Ginu Georgee93abac2024-06-14 17:35:27 +05301656 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1657 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001658 sdbusplus::message::object_path(
1659 "/xyz/openbmc_project/control/host0/boot/one_time"),
1660 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301661 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001662}
1663
1664/**
1665 * @brief Sets boot properties into DBUS object(s).
1666 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001667 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301668 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301669 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001670 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301671 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001672inline void
1673 setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1674 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301675{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001676 std::string bootSourceStr;
1677 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001678
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001679 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301680 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001681 return;
1682 }
1683
1684 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001685 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001686 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001687 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1688 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001689 {
Ed Tanous62598e32023-07-17 17:06:25 -07001690 BMCWEB_LOG_DEBUG(
1691 "Invalid property value for BootSourceOverrideTarget: {}",
1692 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001693 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001694 "BootSourceTargetOverride");
1695 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001696 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301697
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001698 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001699 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1700 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001701
Ginu Georgee93abac2024-06-14 17:35:27 +05301702 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1703 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001704 sdbusplus::message::object_path(
1705 "/xyz/openbmc_project/control/host0/boot"),
1706 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301707 bootSourceStr);
1708 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1709 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001710 sdbusplus::message::object_path(
1711 "/xyz/openbmc_project/control/host0/boot"),
1712 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301713 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001714}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001715
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001716/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001717 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301718 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001719 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301720 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001721 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301722 * @param[in] bootEnable The boot override enable from incoming RF request.
1723 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001724 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301725 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001726
Ed Tanousac106bf2023-06-07 09:24:59 -07001727inline void
1728 setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1729 const std::optional<std::string>& bootSource,
1730 const std::optional<std::string>& bootType,
1731 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732{
Ed Tanous62598e32023-07-17 17:06:25 -07001733 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301734
Ed Tanousac106bf2023-06-07 09:24:59 -07001735 setBootModeOrSource(asyncResp, bootSource);
1736 setBootType(asyncResp, bootType);
1737 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301738}
1739
George Liuc6a620f2020-04-10 17:18:11 +08001740/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001741 * @brief Sets AssetTag
1742 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001743 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001744 * @param[in] assetTag "AssetTag" from request.
1745 *
1746 * @return None.
1747 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001748inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001749 const std::string& assetTag)
1750{
George Liue99073f2022-12-09 11:06:16 +08001751 constexpr std::array<std::string_view, 1> interfaces = {
1752 "xyz.openbmc_project.Inventory.Item.System"};
1753 dbus::utility::getSubTree(
1754 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001755 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001756 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001757 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001758 if (ec)
1759 {
Ed Tanous62598e32023-07-17 17:06:25 -07001760 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001761 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001762 return;
1763 }
1764 if (subtree.empty())
1765 {
Ed Tanous62598e32023-07-17 17:06:25 -07001766 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001767 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001768 return;
1769 }
1770 // Assume only 1 system D-Bus object
1771 // Throw an error if there is more than 1
1772 if (subtree.size() > 1)
1773 {
Ed Tanous62598e32023-07-17 17:06:25 -07001774 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001775 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001776 return;
1777 }
1778 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1779 {
Ed Tanous62598e32023-07-17 17:06:25 -07001780 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001781 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001782 return;
1783 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001784
Ed Tanous002d39b2022-05-31 08:59:27 -07001785 const std::string& path = subtree[0].first;
1786 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001787
Ed Tanous002d39b2022-05-31 08:59:27 -07001788 if (service.empty())
1789 {
Ed Tanous62598e32023-07-17 17:06:25 -07001790 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001791 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001792 return;
1793 }
1794
Ginu Georgee93abac2024-06-14 17:35:27 +05301795 setDbusProperty(asyncResp, "AssetTag", service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001796 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
Ginu Georgee93abac2024-06-14 17:35:27 +05301797 "AssetTag", assetTag);
Patrick Williams5a39f772023-10-20 11:20:21 -05001798 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001799}
1800
1801/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001802 * @brief Validate the specified stopBootOnFault is valid and return the
1803 * stopBootOnFault name associated with that string
1804 *
1805 * @param[in] stopBootOnFaultString String representing the desired
1806 * stopBootOnFault
1807 *
1808 * @return stopBootOnFault value or empty if incoming value is not valid
1809 */
1810inline std::optional<bool>
1811 validstopBootOnFault(const std::string& stopBootOnFaultString)
1812{
1813 if (stopBootOnFaultString == "AnyFault")
1814 {
1815 return true;
1816 }
1817
1818 if (stopBootOnFaultString == "Never")
1819 {
1820 return false;
1821 }
1822
1823 return std::nullopt;
1824}
1825
1826/**
1827 * @brief Sets stopBootOnFault
1828 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001829 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001830 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1831 *
1832 * @return None.
1833 */
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001834inline void
1835 setStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1836 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001837{
Ed Tanous62598e32023-07-17 17:06:25 -07001838 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001839
1840 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1841 if (!stopBootEnabled)
1842 {
Ed Tanous62598e32023-07-17 17:06:25 -07001843 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1844 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001845 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001846 "StopBootOnFault");
1847 return;
1848 }
1849
Ginu Georgee93abac2024-06-14 17:35:27 +05301850 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1851 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001852 sdbusplus::message::object_path(
1853 "/xyz/openbmc_project/logging/settings"),
1854 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301855 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001856}
1857
1858/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001859 * @brief Sets automaticRetry (Auto Reboot)
1860 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001861 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001862 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1863 *
1864 * @return None.
1865 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001866inline void
1867 setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1868 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001869{
Ed Tanous62598e32023-07-17 17:06:25 -07001870 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001871
1872 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001873 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001874
1875 if (automaticRetryConfig == "Disabled")
1876 {
1877 autoRebootEnabled = false;
1878 }
1879 else if (automaticRetryConfig == "RetryAttempts")
1880 {
1881 autoRebootEnabled = true;
1882 }
1883 else
1884 {
Ed Tanous62598e32023-07-17 17:06:25 -07001885 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1886 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001887 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001888 "AutomaticRetryConfig");
1889 return;
1890 }
1891
Ginu Georgee93abac2024-06-14 17:35:27 +05301892 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1893 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001894 sdbusplus::message::object_path(
1895 "/xyz/openbmc_project/control/host0/auto_reboot"),
1896 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301897 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001898}
1899
Ed Tanous8d69c662023-06-21 10:29:06 -07001900inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1901{
1902 if (policy == "AlwaysOn")
1903 {
1904 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1905 }
1906 if (policy == "AlwaysOff")
1907 {
1908 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1909 }
1910 if (policy == "LastState")
1911 {
1912 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1913 }
1914 return "";
1915}
1916
Gunnar Mills69f35302020-05-17 16:06:31 -05001917/**
George Liuc6a620f2020-04-10 17:18:11 +08001918 * @brief Sets power restore policy properties.
1919 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001920 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001921 * @param[in] policy power restore policy properties from request.
1922 *
1923 * @return None.
1924 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001925inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001926 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous8d69c662023-06-21 10:29:06 -07001927 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001928{
Ed Tanous62598e32023-07-17 17:06:25 -07001929 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001930
Ed Tanous8d69c662023-06-21 10:29:06 -07001931 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001932
Ed Tanous8d69c662023-06-21 10:29:06 -07001933 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001934 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001935 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001936 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001937 return;
1938 }
1939
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001940 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301941 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001942 sdbusplus::message::object_path(
1943 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001944 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301945 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001946}
1947
AppaRao Pulia6349912019-10-18 17:16:08 +05301948/**
1949 * @brief Retrieves provisioning status
1950 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001951 * @param[in] asyncResp Shared pointer for completing asynchronous
1952 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301953 *
1954 * @return None.
1955 */
Ed Tanous25b54db2024-04-17 15:40:31 -07001956inline void
1957 getProvisioningStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301958{
Ed Tanous62598e32023-07-17 17:06:25 -07001959 BMCWEB_LOG_DEBUG("Get OEM information.");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001960 sdbusplus::asio::getAllProperties(
1961 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1962 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001963 [asyncResp](const boost::system::error_code& ec,
1964 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001965 nlohmann::json& oemPFR =
Ed Tanousac106bf2023-06-07 09:24:59 -07001966 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1967 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
Ed Tanous1d834d42024-07-12 11:38:40 -07001968 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1969 oemPFR["@odata.type"] = "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001970
Ed Tanous002d39b2022-05-31 08:59:27 -07001971 if (ec)
1972 {
Ed Tanous62598e32023-07-17 17:06:25 -07001973 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001974 // not an error, don't have to have the interface
1975 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1976 return;
1977 }
1978
1979 const bool* provState = nullptr;
1980 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001981
1982 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001983 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1984 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001985
1986 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001987 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001988 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001989 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001990 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301991
Ed Tanous002d39b2022-05-31 08:59:27 -07001992 if ((provState == nullptr) || (lockState == nullptr))
1993 {
Ed Tanous62598e32023-07-17 17:06:25 -07001994 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
Ed Tanousac106bf2023-06-07 09:24:59 -07001995 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001996 return;
1997 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301998
Ed Tanous25b54db2024-04-17 15:40:31 -07001999 if (*provState)
Ed Tanous002d39b2022-05-31 08:59:27 -07002000 {
Ed Tanous25b54db2024-04-17 15:40:31 -07002001 if (*lockState)
AppaRao Pulia6349912019-10-18 17:16:08 +05302002 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002003 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302004 }
2005 else
2006 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002007 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302008 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002009 }
2010 else
2011 {
2012 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2013 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002014 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302015}
AppaRao Pulia6349912019-10-18 17:16:08 +05302016
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302017/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002018 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002019 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002020 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002021 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002022 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002023 */
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002024inline computer_system::PowerMode
2025 translatePowerModeString(const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002026{
Chris Cainb6655102024-02-01 14:35:33 -06002027 using PowerMode = computer_system::PowerMode;
2028
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002029 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002030 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002031 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002032 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002033 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002034 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002035 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002036 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002037 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002038 if (modeString ==
2039 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002040 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002041 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002042 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002043 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002044 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2045 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002046 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002047 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002048 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002049 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2050 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002051 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002052 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002053 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002054 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2055 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002056 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002057 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002058 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002059 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002060 return PowerMode::OEM;
2061 }
2062 // Any other values would be invalid
2063 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2064 return PowerMode::Invalid;
2065}
2066
2067inline void
2068 afterGetPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2069 const boost::system::error_code& ec,
2070 const dbus::utility::DBusPropertiesMap& properties)
2071{
2072 if (ec)
2073 {
2074 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2075 messages::internalError(asyncResp->res);
2076 return;
2077 }
2078
2079 std::string powerMode;
2080 const std::vector<std::string>* allowedModes = nullptr;
2081 const bool success = sdbusplus::unpackPropertiesNoThrow(
2082 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2083 "AllowedPowerModes", allowedModes);
2084
2085 if (!success)
2086 {
2087 messages::internalError(asyncResp->res);
2088 return;
2089 }
2090
2091 nlohmann::json::array_t modeList;
2092 if (allowedModes == nullptr)
2093 {
2094 modeList.emplace_back("Static");
2095 modeList.emplace_back("MaximumPerformance");
2096 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002097 }
2098 else
2099 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002100 for (const auto& aMode : *allowedModes)
2101 {
2102 computer_system::PowerMode modeValue =
2103 translatePowerModeString(aMode);
2104 if (modeValue == computer_system::PowerMode::Invalid)
2105 {
2106 messages::internalError(asyncResp->res);
2107 continue;
2108 }
2109 modeList.emplace_back(modeValue);
2110 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002111 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002112 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002113
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002114 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2115 const computer_system::PowerMode modeValue =
2116 translatePowerModeString(powerMode);
2117 if (modeValue == computer_system::PowerMode::Invalid)
2118 {
2119 messages::internalError(asyncResp->res);
2120 return;
2121 }
2122 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2123}
Chris Cain3a2d04242021-05-28 16:57:10 -05002124/**
2125 * @brief Retrieves system power mode
2126 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002127 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002128 *
2129 * @return None.
2130 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002131inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002132{
Ed Tanous62598e32023-07-17 17:06:25 -07002133 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002134
2135 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002136 constexpr std::array<std::string_view, 1> interfaces = {
2137 "xyz.openbmc_project.Control.Power.Mode"};
2138 dbus::utility::getSubTree(
2139 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002140 [asyncResp](const boost::system::error_code& ec,
2141 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002142 if (ec)
2143 {
Ed Tanous62598e32023-07-17 17:06:25 -07002144 BMCWEB_LOG_DEBUG("DBUS response error on Power.Mode GetSubTree {}",
2145 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002146 // This is an optional D-Bus object so just return if
2147 // error occurs
2148 return;
2149 }
2150 if (subtree.empty())
2151 {
2152 // As noted above, this is an optional interface so just return
2153 // if there is no instance found
2154 return;
2155 }
2156 if (subtree.size() > 1)
2157 {
2158 // More then one PowerMode object is not supported and is an
2159 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002160 BMCWEB_LOG_DEBUG(
2161 "Found more than 1 system D-Bus Power.Mode objects: {}",
2162 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002163 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002164 return;
2165 }
2166 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2167 {
Ed Tanous62598e32023-07-17 17:06:25 -07002168 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002169 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002170 return;
2171 }
2172 const std::string& path = subtree[0].first;
2173 const std::string& service = subtree[0].second.begin()->first;
2174 if (service.empty())
2175 {
Ed Tanous62598e32023-07-17 17:06:25 -07002176 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002177 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002178 return;
2179 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002180
2181 // Valid Power Mode object found, now read the mode properties
2182 sdbusplus::asio::getAllProperties(
Ed Tanous002d39b2022-05-31 08:59:27 -07002183 *crow::connections::systemBus, service, path,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002184 "xyz.openbmc_project.Control.Power.Mode",
Ed Tanousac106bf2023-06-07 09:24:59 -07002185 [asyncResp](const boost::system::error_code& ec2,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002186 const dbus::utility::DBusPropertiesMap& properties) {
2187 afterGetPowerMode(asyncResp, ec2, properties);
George Liue99073f2022-12-09 11:06:16 +08002188 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002189 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002190}
2191
2192/**
2193 * @brief Validate the specified mode is valid and return the PowerMode
2194 * name associated with that string
2195 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002196 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002197 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002198 *
2199 * @return PowerMode value or empty string if mode is not valid
2200 */
2201inline std::string
Ed Tanousac106bf2023-06-07 09:24:59 -07002202 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cainb6655102024-02-01 14:35:33 -06002203 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002204{
Chris Cainb6655102024-02-01 14:35:33 -06002205 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002206 std::string mode;
2207
Chris Cainb6655102024-02-01 14:35:33 -06002208 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002209 {
2210 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2211 }
Chris Cainb6655102024-02-01 14:35:33 -06002212 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002213 {
George Liu0fda0f12021-11-16 10:06:17 +08002214 mode =
2215 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002216 }
Chris Cainb6655102024-02-01 14:35:33 -06002217 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002218 {
2219 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2220 }
Chris Cainb6655102024-02-01 14:35:33 -06002221 else if (modeValue == PowerMode::BalancedPerformance)
2222 {
2223 mode =
2224 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2225 }
2226 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2227 {
2228 mode =
2229 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2230 }
2231 else if (modeValue == PowerMode::EfficiencyFavorPower)
2232 {
2233 mode =
2234 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2235 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002236 else
2237 {
Chris Cainb6655102024-02-01 14:35:33 -06002238 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002239 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002240 }
2241 return mode;
2242}
2243
2244/**
2245 * @brief Sets system power mode.
2246 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002247 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002248 * @param[in] pmode System power mode from request.
2249 *
2250 * @return None.
2251 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002252inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002253 const std::string& pmode)
2254{
Ed Tanous62598e32023-07-17 17:06:25 -07002255 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002256
Ed Tanousac106bf2023-06-07 09:24:59 -07002257 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002258 if (powerMode.empty())
2259 {
2260 return;
2261 }
2262
2263 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002264 constexpr std::array<std::string_view, 1> interfaces = {
2265 "xyz.openbmc_project.Control.Power.Mode"};
2266 dbus::utility::getSubTree(
2267 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002268 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002269 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002270 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002271 if (ec)
2272 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002273 BMCWEB_LOG_ERROR("DBUS response error on Power.Mode GetSubTree {}",
Ed Tanous62598e32023-07-17 17:06:25 -07002274 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002275 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002276 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002277 return;
2278 }
2279 if (subtree.empty())
2280 {
2281 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002282 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002283 "PowerMode");
2284 return;
2285 }
2286 if (subtree.size() > 1)
2287 {
2288 // More then one PowerMode object is not supported and is an
2289 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002290 BMCWEB_LOG_DEBUG(
2291 "Found more than 1 system D-Bus Power.Mode objects: {}",
2292 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002293 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002294 return;
2295 }
2296 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2297 {
Ed Tanous62598e32023-07-17 17:06:25 -07002298 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002299 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002300 return;
2301 }
2302 const std::string& path = subtree[0].first;
2303 const std::string& service = subtree[0].second.begin()->first;
2304 if (service.empty())
2305 {
Ed Tanous62598e32023-07-17 17:06:25 -07002306 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002307 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002308 return;
2309 }
2310
Ed Tanous62598e32023-07-17 17:06:25 -07002311 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002312
2313 // Set the Power Mode property
Ginu Georgee93abac2024-06-14 17:35:27 +05302314 setDbusProperty(asyncResp, "PowerMode", service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002315 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05302316 powerMode);
Patrick Williams5a39f772023-10-20 11:20:21 -05002317 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002318}
2319
2320/**
Yong Li51709ff2019-09-30 14:13:04 +08002321 * @brief Translates watchdog timeout action DBUS property value to redfish.
2322 *
2323 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2324 *
2325 * @return Returns as a string, the timeout action in Redfish terms. If
2326 * translation cannot be done, returns an empty string.
2327 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002328inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002329{
2330 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2331 {
2332 return "None";
2333 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002334 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002335 {
2336 return "ResetSystem";
2337 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002338 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002339 {
2340 return "PowerDown";
2341 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002342 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002343 {
2344 return "PowerCycle";
2345 }
2346
2347 return "";
2348}
2349
2350/**
Yong Lic45f0082019-10-10 14:19:01 +08002351 *@brief Translates timeout action from Redfish to DBUS property value.
2352 *
2353 *@param[in] rfAction The timeout action in Redfish.
2354 *
2355 *@return Returns as a string, the time_out action as expected by DBUS.
2356 *If translation cannot be done, returns an empty string.
2357 */
2358
Ed Tanous23a21a12020-07-25 04:45:05 +00002359inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002360{
2361 if (rfAction == "None")
2362 {
2363 return "xyz.openbmc_project.State.Watchdog.Action.None";
2364 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002365 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002366 {
2367 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2368 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002369 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002370 {
2371 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2372 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002373 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002374 {
2375 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2376 }
2377
2378 return "";
2379}
2380
2381/**
Yong Li51709ff2019-09-30 14:13:04 +08002382 * @brief Retrieves host watchdog timer properties over DBUS
2383 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002384 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002385 *
2386 * @return None.
2387 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002388inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002389 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002390{
Ed Tanous62598e32023-07-17 17:06:25 -07002391 BMCWEB_LOG_DEBUG("Get host watchodg");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002392 sdbusplus::asio::getAllProperties(
2393 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2394 "/xyz/openbmc_project/watchdog/host0",
2395 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002396 [asyncResp](const boost::system::error_code& ec,
2397 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002398 if (ec)
2399 {
2400 // watchdog service is stopped
Ed Tanous62598e32023-07-17 17:06:25 -07002401 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002402 return;
2403 }
2404
Ed Tanous62598e32023-07-17 17:06:25 -07002405 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002406
2407 nlohmann::json& hostWatchdogTimer =
Ed Tanousac106bf2023-06-07 09:24:59 -07002408 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002409
2410 // watchdog service is running/enabled
2411 hostWatchdogTimer["Status"]["State"] = "Enabled";
2412
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002413 const bool* enabled = nullptr;
2414 const std::string* expireAction = nullptr;
2415
2416 const bool success = sdbusplus::unpackPropertiesNoThrow(
2417 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2418 "ExpireAction", expireAction);
2419
2420 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002421 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002422 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002423 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002424 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002425
2426 if (enabled != nullptr)
2427 {
2428 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2429 }
2430
2431 if (expireAction != nullptr)
2432 {
2433 std::string action = dbusToRfWatchdogAction(*expireAction);
2434 if (action.empty())
2435 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002436 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002437 return;
2438 }
2439 hostWatchdogTimer["TimeoutAction"] = action;
2440 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002441 });
Yong Li51709ff2019-09-30 14:13:04 +08002442}
2443
2444/**
Yong Lic45f0082019-10-10 14:19:01 +08002445 * @brief Sets Host WatchDog Timer properties.
2446 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002447 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002448 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2449 * RF request.
2450 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2451 *
2452 * @return None.
2453 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002454inline void
2455 setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2456 const std::optional<bool> wdtEnable,
2457 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002458{
Ed Tanous62598e32023-07-17 17:06:25 -07002459 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002460
2461 if (wdtTimeOutAction)
2462 {
2463 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2464 // check if TimeOut Action is Valid
2465 if (wdtTimeOutActStr.empty())
2466 {
Ed Tanous62598e32023-07-17 17:06:25 -07002467 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2468 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002469 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002470 "TimeoutAction");
2471 return;
2472 }
2473
Ginu Georgee93abac2024-06-14 17:35:27 +05302474 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2475 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002476 sdbusplus::message::object_path(
2477 "/xyz/openbmc_project/watchdog/host0"),
2478 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302479 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002480 }
2481
2482 if (wdtEnable)
2483 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302484 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2485 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002486 sdbusplus::message::object_path(
2487 "/xyz/openbmc_project/watchdog/host0"),
2488 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302489 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002490 }
2491}
2492
Chris Cain37bbf982021-09-20 10:53:09 -05002493/**
2494 * @brief Parse the Idle Power Saver properties into json
2495 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002496 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002497 * @param[in] properties IPS property data from DBus.
2498 *
2499 * @return true if successful
2500 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002501inline bool
Ed Tanousac106bf2023-06-07 09:24:59 -07002502 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002503 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002504{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002505 const bool* enabled = nullptr;
2506 const uint8_t* enterUtilizationPercent = nullptr;
2507 const uint64_t* enterDwellTime = nullptr;
2508 const uint8_t* exitUtilizationPercent = nullptr;
2509 const uint64_t* exitDwellTime = nullptr;
2510
2511 const bool success = sdbusplus::unpackPropertiesNoThrow(
2512 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002513 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2514 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2515 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002516
2517 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002518 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002519 return false;
2520 }
2521
2522 if (enabled != nullptr)
2523 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002524 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002525 }
2526
2527 if (enterUtilizationPercent != nullptr)
2528 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002529 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002530 *enterUtilizationPercent;
2531 }
2532
2533 if (enterDwellTime != nullptr)
2534 {
2535 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002536 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002537 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2538 .count();
2539 }
2540
2541 if (exitUtilizationPercent != nullptr)
2542 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002543 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002544 *exitUtilizationPercent;
2545 }
2546
2547 if (exitDwellTime != nullptr)
2548 {
2549 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002550 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002551 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2552 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002553 }
2554
2555 return true;
2556}
2557
2558/**
2559 * @brief Retrieves host watchdog timer properties over DBUS
2560 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002561 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002562 *
2563 * @return None.
2564 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002565inline void
2566 getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002567{
Ed Tanous62598e32023-07-17 17:06:25 -07002568 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002569
2570 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002571 constexpr std::array<std::string_view, 1> interfaces = {
2572 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2573 dbus::utility::getSubTree(
2574 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002575 [asyncResp](const boost::system::error_code& ec,
2576 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002577 if (ec)
2578 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002579 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002580 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2581 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002582 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002583 return;
2584 }
2585 if (subtree.empty())
2586 {
2587 // This is an optional interface so just return
2588 // if there is no instance found
Ed Tanous62598e32023-07-17 17:06:25 -07002589 BMCWEB_LOG_DEBUG("No instances found");
Ed Tanous002d39b2022-05-31 08:59:27 -07002590 return;
2591 }
2592 if (subtree.size() > 1)
2593 {
2594 // More then one PowerIdlePowerSaver object is not supported and
2595 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002596 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2597 "Power.IdlePowerSaver objects: {}",
2598 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002599 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002600 return;
2601 }
2602 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2603 {
Ed Tanous62598e32023-07-17 17:06:25 -07002604 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002605 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002606 return;
2607 }
2608 const std::string& path = subtree[0].first;
2609 const std::string& service = subtree[0].second.begin()->first;
2610 if (service.empty())
2611 {
Ed Tanous62598e32023-07-17 17:06:25 -07002612 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002613 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002614 return;
2615 }
2616
2617 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002618 sdbusplus::asio::getAllProperties(
2619 *crow::connections::systemBus, service, path,
2620 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanousac106bf2023-06-07 09:24:59 -07002621 [asyncResp](const boost::system::error_code& ec2,
2622 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002623 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002624 {
Ed Tanous62598e32023-07-17 17:06:25 -07002625 BMCWEB_LOG_ERROR(
2626 "DBUS response error on IdlePowerSaver GetAll: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002627 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002628 return;
2629 }
2630
Ed Tanousac106bf2023-06-07 09:24:59 -07002631 if (!parseIpsProperties(asyncResp, properties))
Ed Tanous002d39b2022-05-31 08:59:27 -07002632 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002633 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002634 return;
2635 }
George Liue99073f2022-12-09 11:06:16 +08002636 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002637 });
Chris Cain37bbf982021-09-20 10:53:09 -05002638
Ed Tanous62598e32023-07-17 17:06:25 -07002639 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002640}
2641
2642/**
2643 * @brief Sets Idle Power Saver properties.
2644 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002645 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002646 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2647 * RF request.
2648 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2649 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2650 * before entering idle state.
2651 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2652 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2653 * before exiting idle state
2654 *
2655 * @return None.
2656 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002657inline void
2658 setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2659 const std::optional<bool> ipsEnable,
2660 const std::optional<uint8_t> ipsEnterUtil,
2661 const std::optional<uint64_t> ipsEnterTime,
2662 const std::optional<uint8_t> ipsExitUtil,
2663 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002664{
Ed Tanous62598e32023-07-17 17:06:25 -07002665 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002666
2667 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002668 constexpr std::array<std::string_view, 1> interfaces = {
2669 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2670 dbus::utility::getSubTree(
2671 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002672 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002673 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002674 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002675 if (ec)
2676 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002677 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002678 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2679 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002680 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002681 return;
2682 }
2683 if (subtree.empty())
2684 {
2685 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002686 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002687 "IdlePowerSaver");
2688 return;
2689 }
2690 if (subtree.size() > 1)
2691 {
2692 // More then one PowerIdlePowerSaver object is not supported and
2693 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002694 BMCWEB_LOG_DEBUG(
2695 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2696 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002697 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002698 return;
2699 }
2700 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2701 {
Ed Tanous62598e32023-07-17 17:06:25 -07002702 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002703 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002704 return;
2705 }
2706 const std::string& path = subtree[0].first;
2707 const std::string& service = subtree[0].second.begin()->first;
2708 if (service.empty())
2709 {
Ed Tanous62598e32023-07-17 17:06:25 -07002710 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002711 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002712 return;
2713 }
Chris Cain37bbf982021-09-20 10:53:09 -05002714
Ed Tanous002d39b2022-05-31 08:59:27 -07002715 // Valid Power IdlePowerSaver object found, now set any values that
2716 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002717
Ed Tanous002d39b2022-05-31 08:59:27 -07002718 if (ipsEnable)
2719 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302720 setDbusProperty(asyncResp, "IdlePowerSaver/Enabled", service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002721 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302722 "Enabled", *ipsEnable);
Ed Tanous002d39b2022-05-31 08:59:27 -07002723 }
2724 if (ipsEnterUtil)
2725 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302726 setDbusProperty(asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2727 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002728 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302729 "EnterUtilizationPercent", *ipsEnterUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002730 }
2731 if (ipsEnterTime)
2732 {
2733 // Convert from seconds into milliseconds for DBus
2734 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
Ginu Georgee93abac2024-06-14 17:35:27 +05302735 setDbusProperty(asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds",
2736 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002737 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302738 "EnterDwellTime", timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002739 }
2740 if (ipsExitUtil)
2741 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302742 setDbusProperty(asyncResp, "IdlePowerSaver/ExitUtilizationPercent",
2743 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002744 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302745 "ExitUtilizationPercent", *ipsExitUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002746 }
2747 if (ipsExitTime)
2748 {
2749 // Convert from seconds into milliseconds for DBus
2750 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
Ginu Georgee93abac2024-06-14 17:35:27 +05302751 setDbusProperty(asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds",
2752 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002753 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302754 "ExitDwellTime", timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002755 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002756 });
Chris Cain37bbf982021-09-20 10:53:09 -05002757
Ed Tanous62598e32023-07-17 17:06:25 -07002758 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002759}
2760
Ed Tanousc1e219d2023-06-07 10:34:33 -07002761inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002762 crow::App& app, const crow::Request& req,
2763 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2764{
2765 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2766 {
2767 return;
2768 }
2769 asyncResp->res.addHeader(
2770 boost::beast::http::field::link,
2771 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2772}
2773
Ed Tanousc1e219d2023-06-07 10:34:33 -07002774inline void handleComputerSystemCollectionGet(
2775 crow::App& app, const crow::Request& req,
2776 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2777{
2778 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2779 {
2780 return;
2781 }
2782
2783 asyncResp->res.addHeader(
2784 boost::beast::http::field::link,
2785 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2786 asyncResp->res.jsonValue["@odata.type"] =
2787 "#ComputerSystemCollection.ComputerSystemCollection";
2788 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2789 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2790
2791 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2792 ifaceArray = nlohmann::json::array();
Ed Tanous25b54db2024-04-17 15:40:31 -07002793 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002794 {
2795 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2796 // Option currently returns no systems. TBD
2797 return;
2798 }
2799 asyncResp->res.jsonValue["Members@odata.count"] = 1;
2800 nlohmann::json::object_t system;
Ed Tanous253f11b2024-05-16 09:38:31 -07002801 system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
2802 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002803 ifaceArray.emplace_back(std::move(system));
2804 sdbusplus::asio::getProperty<std::string>(
2805 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2806 "/xyz/openbmc_project/network/hypervisor",
2807 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
2808 [asyncResp](const boost::system::error_code& ec2,
2809 const std::string& /*hostName*/) {
2810 if (ec2)
2811 {
2812 return;
2813 }
2814 auto val = asyncResp->res.jsonValue.find("Members@odata.count");
2815 if (val == asyncResp->res.jsonValue.end())
2816 {
Ed Tanous62598e32023-07-17 17:06:25 -07002817 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002818 return;
2819 }
Asmitha Karunanithi67b15902024-07-12 12:52:51 -05002820 int64_t* count = val->get_ptr<int64_t*>();
Ed Tanousc1e219d2023-06-07 10:34:33 -07002821 if (count == nullptr)
2822 {
Ed Tanous62598e32023-07-17 17:06:25 -07002823 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002824 return;
2825 }
2826 *count = *count + 1;
Ed Tanous62598e32023-07-17 17:06:25 -07002827 BMCWEB_LOG_DEBUG("Hypervisor is available");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002828 nlohmann::json& ifaceArray2 = asyncResp->res.jsonValue["Members"];
2829 nlohmann::json::object_t hypervisor;
2830 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2831 ifaceArray2.emplace_back(std::move(hypervisor));
Patrick Williams5a39f772023-10-20 11:20:21 -05002832 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07002833}
2834
Yong Lic45f0082019-10-10 14:19:01 +08002835/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002836 * Function transceives data with dbus directly.
2837 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002838inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839{
Patrick Williams89492a12023-05-10 07:51:34 -05002840 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2841 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2842 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002844 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002845
2846 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002847 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002848 if (ec)
2849 {
Ed Tanous62598e32023-07-17 17:06:25 -07002850 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002851 messages::internalError(asyncResp->res);
2852 return;
2853 }
2854 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05002855 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002856 serviceName, objectPath, interfaceName, method);
2857}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002858
Ed Tanousc1e219d2023-06-07 10:34:33 -07002859inline void handleComputerSystemResetActionPost(
2860 crow::App& app, const crow::Request& req,
2861 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2862 const std::string& systemName)
2863{
2864 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2865 {
2866 return;
2867 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002868 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002869 {
2870 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2871 systemName);
2872 return;
2873 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002874 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002875 {
2876 // Option currently returns no systems. TBD
2877 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2878 systemName);
2879 return;
2880 }
2881 std::string resetType;
2882 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2883 {
2884 return;
2885 }
2886
2887 // Get the command and host vs. chassis
2888 std::string command;
2889 bool hostCommand = true;
2890 if ((resetType == "On") || (resetType == "ForceOn"))
2891 {
2892 command = "xyz.openbmc_project.State.Host.Transition.On";
2893 hostCommand = true;
2894 }
2895 else if (resetType == "ForceOff")
2896 {
2897 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2898 hostCommand = false;
2899 }
2900 else if (resetType == "ForceRestart")
2901 {
2902 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2903 hostCommand = true;
2904 }
2905 else if (resetType == "GracefulShutdown")
2906 {
2907 command = "xyz.openbmc_project.State.Host.Transition.Off";
2908 hostCommand = true;
2909 }
2910 else if (resetType == "GracefulRestart")
2911 {
2912 command =
2913 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2914 hostCommand = true;
2915 }
2916 else if (resetType == "PowerCycle")
2917 {
2918 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2919 hostCommand = true;
2920 }
2921 else if (resetType == "Nmi")
2922 {
2923 doNMI(asyncResp);
2924 return;
2925 }
2926 else
2927 {
2928 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2929 return;
2930 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002931 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002932
2933 if (hostCommand)
2934 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302935 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002936 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302937 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002938 }
2939 else
2940 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302941 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08002942 statePath / "chassis0",
2943 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302944 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002945 }
2946}
2947
Ed Tanousc1e219d2023-06-07 10:34:33 -07002948inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002949 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002950 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2951 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002952{
2953 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2954 {
2955 return;
2956 }
2957
2958 asyncResp->res.addHeader(
2959 boost::beast::http::field::link,
2960 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2961}
2962
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002963inline void afterPortRequest(
2964 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2965 const boost::system::error_code& ec,
2966 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2967{
2968 if (ec)
2969 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002970 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002971 messages::internalError(asyncResp->res);
2972 return;
2973 }
2974 for (const auto& data : socketData)
2975 {
2976 const std::string& socketPath = get<0>(data);
2977 const std::string& protocolName = get<1>(data);
2978 bool isProtocolEnabled = get<2>(data);
2979 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2980 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2981 // need to retrieve port number for
2982 // obmc-console-ssh service
2983 if (protocolName == "SSH")
2984 {
2985 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002986 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002987 int portNumber) {
2988 if (ec1)
2989 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002990 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002991 messages::internalError(asyncResp->res);
2992 return;
2993 }
2994 nlohmann::json& dataJson1 =
2995 asyncResp->res.jsonValue["SerialConsole"];
2996 dataJson1[protocolName]["Port"] = portNumber;
2997 });
2998 }
2999 }
3000}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003001
3002inline void
3003 handleComputerSystemGet(crow::App& app, const crow::Request& req,
3004 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3005 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003006{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003007 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3008 {
3009 return;
3010 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003011
Ed Tanous25b54db2024-04-17 15:40:31 -07003012 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003013 {
3014 // Option currently returns no systems. TBD
3015 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3016 systemName);
3017 return;
3018 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003019
Ed Tanousc1e219d2023-06-07 10:34:33 -07003020 if (systemName == "hypervisor")
3021 {
3022 handleHypervisorSystemGet(asyncResp);
3023 return;
3024 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003025
Ed Tanous253f11b2024-05-16 09:38:31 -07003026 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003027 {
3028 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3029 systemName);
3030 return;
3031 }
3032 asyncResp->res.addHeader(
3033 boost::beast::http::field::link,
3034 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3035 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003036 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003037 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3038 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003039 asyncResp->res.jsonValue["SystemType"] = "Physical";
3040 asyncResp->res.jsonValue["Description"] = "Computer System";
3041 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003042 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003043 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003044 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3045 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003046
Ed Tanous253f11b2024-05-16 09:38:31 -07003047 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3048 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3049 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3050 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3051 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3052 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003053 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003054 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3055 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003056
Ed Tanousc1e219d2023-06-07 10:34:33 -07003057 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003058 boost::urls::format(
3059 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3060 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003061 asyncResp->res
3062 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003063 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3064 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003065
Ed Tanous253f11b2024-05-16 09:38:31 -07003066 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3067 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3068 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3069 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003070
Ed Tanousc1e219d2023-06-07 10:34:33 -07003071 nlohmann::json::array_t managedBy;
3072 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003073 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3074 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003075 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3076 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3077 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003078
Ed Tanousc1e219d2023-06-07 10:34:33 -07003079 // Fill in SerialConsole info
3080 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3081 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003082
Ed Tanousc1e219d2023-06-07 10:34:33 -07003083 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3084 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3085 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3086 "Press ~. to exit console";
3087 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3088 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003089
Ed Tanous25b54db2024-04-17 15:40:31 -07003090 if constexpr (BMCWEB_KVM)
3091 {
3092 // Fill in GraphicalConsole info
3093 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3094 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3095 4;
3096 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3097 nlohmann::json::array_t({"KVMIP"});
3098 }
James Feistb49ac872019-05-21 15:12:01 -07003099
Ed Tanousc1e219d2023-06-07 10:34:33 -07003100 getMainChassisId(asyncResp,
3101 [](const std::string& chassisId,
3102 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3103 nlohmann::json::array_t chassisArray;
3104 nlohmann::json& chassis = chassisArray.emplace_back();
3105 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3106 chassisId);
3107 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3108 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003109
George Liu59a17e42022-10-08 09:27:47 +08003110 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003111 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3112 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003113 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003114 getHostState(asyncResp);
3115 getBootProperties(asyncResp);
3116 getBootProgress(asyncResp);
3117 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003118 pcie_util::getPCIeDeviceList(asyncResp,
3119 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003120 getHostWatchdogTimer(asyncResp);
3121 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003122 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003123 getAutomaticRetryPolicy(asyncResp);
3124 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003125 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3126 {
3127 getProvisioningStatus(asyncResp);
3128 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003129 getTrustedModuleRequiredToBoot(asyncResp);
3130 getPowerMode(asyncResp);
3131 getIdlePowerSaver(asyncResp);
3132}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003133
Ed Tanousc1e219d2023-06-07 10:34:33 -07003134inline void handleComputerSystemPatch(
3135 crow::App& app, const crow::Request& req,
3136 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3137 const std::string& systemName)
3138{
3139 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3140 {
3141 return;
3142 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003143 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003144 {
3145 // Option currently returns no systems. TBD
3146 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3147 systemName);
3148 return;
3149 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003150 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003151 {
3152 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3153 systemName);
3154 return;
3155 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003156
Ed Tanousc1e219d2023-06-07 10:34:33 -07003157 asyncResp->res.addHeader(
3158 boost::beast::http::field::link,
3159 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003160
Ed Tanousc1e219d2023-06-07 10:34:33 -07003161 std::optional<bool> locationIndicatorActive;
3162 std::optional<std::string> indicatorLed;
3163 std::optional<std::string> assetTag;
3164 std::optional<std::string> powerRestorePolicy;
3165 std::optional<std::string> powerMode;
3166 std::optional<bool> wdtEnable;
3167 std::optional<std::string> wdtTimeOutAction;
3168 std::optional<std::string> bootSource;
3169 std::optional<std::string> bootType;
3170 std::optional<std::string> bootEnable;
3171 std::optional<std::string> bootAutomaticRetry;
3172 std::optional<uint32_t> bootAutomaticRetryAttempts;
3173 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003174 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003175 std::optional<bool> ipsEnable;
3176 std::optional<uint8_t> ipsEnterUtil;
3177 std::optional<uint64_t> ipsEnterTime;
3178 std::optional<uint8_t> ipsExitUtil;
3179 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003180
Ed Tanousc1e219d2023-06-07 10:34:33 -07003181 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003182 if (!json_util::readJsonPatch(
3183 req, asyncResp->res,
3184 "IndicatorLED", indicatorLed,
3185 "LocationIndicatorActive", locationIndicatorActive,
3186 "AssetTag", assetTag,
3187 "PowerRestorePolicy", powerRestorePolicy,
3188 "PowerMode", powerMode,
3189 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3190 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3191 "Boot/BootSourceOverrideTarget", bootSource,
3192 "Boot/BootSourceOverrideMode", bootType,
3193 "Boot/BootSourceOverrideEnabled", bootEnable,
3194 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003195 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003196 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003197 "Boot/StopBootOnFault", stopBootOnFault,
Ed Tanous22d268c2022-05-19 09:39:07 -07003198 "IdlePowerSaver/Enabled", ipsEnable,
3199 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3200 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3201 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3202 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3203 {
3204 return;
3205 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003206 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003207
Ed Tanousc1e219d2023-06-07 10:34:33 -07003208 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003209
Ed Tanousc1e219d2023-06-07 10:34:33 -07003210 if (assetTag)
3211 {
3212 setAssetTag(asyncResp, *assetTag);
3213 }
James Feistb49ac872019-05-21 15:12:01 -07003214
Ed Tanousc1e219d2023-06-07 10:34:33 -07003215 if (wdtEnable || wdtTimeOutAction)
3216 {
3217 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3218 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003219
Ed Tanousc1e219d2023-06-07 10:34:33 -07003220 if (bootSource || bootType || bootEnable)
3221 {
3222 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3223 }
3224 if (bootAutomaticRetry)
3225 {
3226 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3227 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003228
Ed Tanousc1e219d2023-06-07 10:34:33 -07003229 if (bootAutomaticRetryAttempts)
3230 {
3231 setAutomaticRetryAttempts(asyncResp,
3232 bootAutomaticRetryAttempts.value());
3233 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003234
Ed Tanousc1e219d2023-06-07 10:34:33 -07003235 if (bootTrustedModuleRequired)
3236 {
3237 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3238 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003239
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003240 if (stopBootOnFault)
3241 {
3242 setStopBootOnFault(asyncResp, *stopBootOnFault);
3243 }
3244
Ed Tanousc1e219d2023-06-07 10:34:33 -07003245 if (locationIndicatorActive)
3246 {
George Liu59a17e42022-10-08 09:27:47 +08003247 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003248 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003249
Ed Tanousc1e219d2023-06-07 10:34:33 -07003250 // TODO (Gunnar): Remove IndicatorLED after enough time has
3251 // passed
3252 if (indicatorLed)
3253 {
3254 setIndicatorLedState(asyncResp, *indicatorLed);
3255 asyncResp->res.addHeader(boost::beast::http::field::warning,
3256 "299 - \"IndicatorLED is deprecated. Use "
3257 "LocationIndicatorActive instead.\"");
3258 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003259
Ed Tanousc1e219d2023-06-07 10:34:33 -07003260 if (powerRestorePolicy)
3261 {
3262 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3263 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003264
Ed Tanousc1e219d2023-06-07 10:34:33 -07003265 if (powerMode)
3266 {
3267 setPowerMode(asyncResp, *powerMode);
3268 }
Chris Cain37bbf982021-09-20 10:53:09 -05003269
Ed Tanousc1e219d2023-06-07 10:34:33 -07003270 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3271 {
3272 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3273 ipsExitUtil, ipsExitTime);
3274 }
3275}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303276
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003277inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003278 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003279 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003280 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003281{
3282 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3283 {
3284 return;
3285 }
3286 asyncResp->res.addHeader(
3287 boost::beast::http::field::link,
3288 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3289}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003290
3291/**
3292 * @brief Translates allowed host transitions to redfish string
3293 *
3294 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3295 * @param[out] allowableValues The translated host transition(s)
3296 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303297 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003298 * allowableValues. If translation not possible, does nothing to
3299 * allowableValues.
3300 */
3301inline void
3302 dbusToRfAllowedHostTransitions(const std::string& dbusAllowedHostTran,
3303 nlohmann::json::array_t& allowableValues)
3304{
3305 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3306 {
3307 allowableValues.emplace_back(resource::ResetType::On);
3308 allowableValues.emplace_back(resource::ResetType::ForceOn);
3309 }
3310 else if (dbusAllowedHostTran ==
3311 "xyz.openbmc_project.State.Host.Transition.Off")
3312 {
3313 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3314 }
3315 else if (dbusAllowedHostTran ==
3316 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3317 {
3318 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3319 }
3320 else if (dbusAllowedHostTran ==
3321 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3322 {
3323 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3324 }
3325 else
3326 {
3327 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3328 }
3329}
3330
3331inline void afterGetAllowedHostTransitions(
3332 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3333 const boost::system::error_code& ec,
3334 const std::vector<std::string>& allowedHostTransitions)
3335{
3336 nlohmann::json::array_t allowableValues;
3337
3338 // Supported on all systems currently
3339 allowableValues.emplace_back(resource::ResetType::ForceOff);
3340 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3341 allowableValues.emplace_back(resource::ResetType::Nmi);
3342
3343 if (ec)
3344 {
Ed Tanouse715d142024-03-07 15:47:37 -08003345 if ((ec.value() ==
3346 boost::system::linux_error::bad_request_descriptor) ||
3347 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003348 {
3349 // Property not implemented so just return defaults
3350 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3351 allowableValues.emplace_back(resource::ResetType::On);
3352 allowableValues.emplace_back(resource::ResetType::ForceOn);
3353 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3354 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3355 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3356 }
3357 else
3358 {
3359 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3360 messages::internalError(asyncResp->res);
3361 return;
3362 }
3363 }
3364 else
3365 {
3366 for (const std::string& transition : allowedHostTransitions)
3367 {
3368 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3369 dbusToRfAllowedHostTransitions(transition, allowableValues);
3370 }
3371 }
3372
3373 nlohmann::json::object_t parameter;
3374 parameter["Name"] = "ResetType";
3375 parameter["Required"] = true;
3376 parameter["DataType"] = "String";
3377 parameter["AllowableValues"] = std::move(allowableValues);
3378 nlohmann::json::array_t parameters;
3379 parameters.emplace_back(std::move(parameter));
3380 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3381}
3382
Ed Tanousc1e219d2023-06-07 10:34:33 -07003383inline void handleSystemCollectionResetActionGet(
3384 crow::App& app, const crow::Request& req,
3385 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3386 const std::string& systemName)
3387{
3388 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3389 {
3390 return;
3391 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003392 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003393 {
3394 // Option currently returns no systems. TBD
3395 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3396 systemName);
3397 return;
3398 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003399
Ed Tanousc1e219d2023-06-07 10:34:33 -07003400 if (systemName == "hypervisor")
3401 {
3402 handleHypervisorResetActionGet(asyncResp);
3403 return;
3404 }
3405
Ed Tanous253f11b2024-05-16 09:38:31 -07003406 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003407 {
3408 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3409 systemName);
3410 return;
3411 }
3412
3413 asyncResp->res.addHeader(
3414 boost::beast::http::field::link,
3415 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3416
3417 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003418 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3419 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003420 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3421 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3422 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3423
Andrew Geissler33e1f122024-02-26 21:10:16 -06003424 // Look to see if system defines AllowedHostTransitions
3425 sdbusplus::asio::getProperty<std::vector<std::string>>(
3426 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
3427 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
3428 "AllowedHostTransitions",
3429 [asyncResp](const boost::system::error_code& ec,
3430 const std::vector<std::string>& allowedHostTransitions) {
3431 afterGetAllowedHostTransitions(asyncResp, ec, allowedHostTransitions);
3432 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003433}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303434/**
3435 * SystemResetActionInfo derived class for delivering Computer Systems
3436 * ResetType AllowableValues using ResetInfo schema.
3437 */
Ed Tanous100afe52023-06-07 13:30:46 -07003438inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303439{
Ed Tanous100afe52023-06-07 13:30:46 -07003440 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3441 .privileges(redfish::privileges::headComputerSystemCollection)
3442 .methods(boost::beast::http::verb::head)(
3443 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3444
3445 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3446 .privileges(redfish::privileges::getComputerSystemCollection)
3447 .methods(boost::beast::http::verb::get)(
3448 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3449
3450 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3451 .privileges(redfish::privileges::headComputerSystem)
3452 .methods(boost::beast::http::verb::head)(
3453 std::bind_front(handleComputerSystemHead, std::ref(app)));
3454
3455 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3456 .privileges(redfish::privileges::getComputerSystem)
3457 .methods(boost::beast::http::verb::get)(
3458 std::bind_front(handleComputerSystemGet, std::ref(app)));
3459
3460 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3461 .privileges(redfish::privileges::patchComputerSystem)
3462 .methods(boost::beast::http::verb::patch)(
3463 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3464
3465 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3466 .privileges(redfish::privileges::postComputerSystem)
3467 .methods(boost::beast::http::verb::post)(std::bind_front(
3468 handleComputerSystemResetActionPost, std::ref(app)));
3469
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003470 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003471 .privileges(redfish::privileges::headActionInfo)
3472 .methods(boost::beast::http::verb::head)(std::bind_front(
3473 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003474 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003475 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003476 .methods(boost::beast::http::verb::get)(std::bind_front(
3477 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003478}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003479} // namespace redfish