blob: 2687ecf9f918c117480cdb204ea79f5b070270fe [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(
1281 asyncResp, "xyz.openbmc_project.State.Host",
1282 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001283 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001284 "Boot/AutomaticRetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001285}
1286
Ed Tanous8d69c662023-06-21 10:29:06 -07001287inline computer_system::PowerRestorePolicyTypes
1288 redfishPowerRestorePolicyFromDbus(std::string_view value)
1289{
1290 if (value ==
1291 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1292 {
1293 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1294 }
1295 if (value ==
1296 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1297 {
1298 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1299 }
1300 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001301 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001302 {
1303 return computer_system::PowerRestorePolicyTypes::LastState;
1304 }
1305 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1306 {
1307 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1308 }
1309 return computer_system::PowerRestorePolicyTypes::Invalid;
1310}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001311/**
George Liuc6a620f2020-04-10 17:18:11 +08001312 * @brief Retrieves power restore policy over DBUS.
1313 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001314 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001315 *
1316 * @return None.
1317 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001318inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001319 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001320{
Ed Tanous62598e32023-07-17 17:06:25 -07001321 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001322
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001323 sdbusplus::asio::getProperty<std::string>(
1324 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1325 "/xyz/openbmc_project/control/host0/power_restore_policy",
1326 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001327 [asyncResp](const boost::system::error_code& ec,
1328 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001329 if (ec)
1330 {
Ed Tanous62598e32023-07-17 17:06:25 -07001331 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001332 return;
1333 }
Ed Tanous8d69c662023-06-21 10:29:06 -07001334 computer_system::PowerRestorePolicyTypes restore =
1335 redfishPowerRestorePolicyFromDbus(policy);
1336 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -07001337 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001338 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001339 return;
1340 }
George Liuc6a620f2020-04-10 17:18:11 +08001341
Ed Tanous8d69c662023-06-21 10:29:06 -07001342 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
Patrick Williams5a39f772023-10-20 11:20:21 -05001343 });
George Liuc6a620f2020-04-10 17:18:11 +08001344}
1345
1346/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001347 * @brief Stop Boot On Fault over DBUS.
1348 *
1349 * @param[in] asyncResp Shared pointer for generating response message.
1350 *
1351 * @return None.
1352 */
1353inline void
1354 getStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1355{
Ed Tanous62598e32023-07-17 17:06:25 -07001356 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001357
1358 sdbusplus::asio::getProperty<bool>(
1359 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1360 "/xyz/openbmc_project/logging/settings",
1361 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1362 [asyncResp](const boost::system::error_code& ec, bool value) {
1363 if (ec)
1364 {
1365 if (ec.value() != EBADR)
1366 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001367 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001368 messages::internalError(asyncResp->res);
1369 }
1370 return;
1371 }
1372
1373 if (value)
1374 {
1375 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "AnyFault";
1376 }
1377 else
1378 {
1379 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "Never";
1380 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001381 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001382}
1383
1384/**
Ali Ahmed19817712021-06-29 17:01:52 -05001385 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1386 * TPM is required for booting the host.
1387 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001388 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001389 *
1390 * @return None.
1391 */
1392inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001393 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001394{
Ed Tanous62598e32023-07-17 17:06:25 -07001395 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001396 constexpr std::array<std::string_view, 1> interfaces = {
1397 "xyz.openbmc_project.Control.TPM.Policy"};
1398 dbus::utility::getSubTree(
1399 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001400 [asyncResp](const boost::system::error_code& ec,
1401 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001402 if (ec)
1403 {
Ed Tanous62598e32023-07-17 17:06:25 -07001404 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}",
1405 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001406 // This is an optional D-Bus object so just return if
1407 // error occurs
1408 return;
1409 }
1410 if (subtree.empty())
1411 {
1412 // As noted above, this is an optional interface so just return
1413 // if there is no instance found
1414 return;
1415 }
1416
1417 /* When there is more than one TPMEnable object... */
1418 if (subtree.size() > 1)
1419 {
Ed Tanous62598e32023-07-17 17:06:25 -07001420 BMCWEB_LOG_DEBUG(
1421 "DBUS response has more than 1 TPM Enable object:{}",
1422 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001423 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001424 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001425 return;
1426 }
1427
1428 // Make sure the Dbus response map has a service and objectPath
1429 // field
1430 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1431 {
Ed Tanous62598e32023-07-17 17:06:25 -07001432 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001433 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001434 return;
1435 }
1436
1437 const std::string& path = subtree[0].first;
1438 const std::string& serv = subtree[0].second.begin()->first;
1439
1440 // Valid TPM Enable object found, now reading the current value
1441 sdbusplus::asio::getProperty<bool>(
1442 *crow::connections::systemBus, serv, path,
1443 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanousac106bf2023-06-07 09:24:59 -07001444 [asyncResp](const boost::system::error_code& ec2,
1445 bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001446 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001447 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001448 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001449 ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001450 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001451 return;
1452 }
1453
Ed Tanous002d39b2022-05-31 08:59:27 -07001454 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001455 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001456 asyncResp->res
1457 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001458 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001459 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001460 else
1461 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001462 asyncResp->res
1463 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001464 "Disabled";
1465 }
George Liue99073f2022-12-09 11:06:16 +08001466 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001467 });
Ali Ahmed19817712021-06-29 17:01:52 -05001468}
1469
1470/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001471 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1472 * TPM is required for booting the host.
1473 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001474 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001475 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1476 *
1477 * @return None.
1478 */
1479inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001480 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001481{
Ed Tanous62598e32023-07-17 17:06:25 -07001482 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001483 constexpr std::array<std::string_view, 1> interfaces = {
1484 "xyz.openbmc_project.Control.TPM.Policy"};
1485 dbus::utility::getSubTree(
1486 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001487 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001488 tpmRequired](const boost::system::error_code& ec,
1489 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001490 if (ec)
1491 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001492 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001493 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001494 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001495 return;
1496 }
1497 if (subtree.empty())
1498 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001499 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07001500 "TrustedModuleRequiredToBoot");
1501 return;
1502 }
1503
1504 /* When there is more than one TPMEnable object... */
1505 if (subtree.size() > 1)
1506 {
Ed Tanous62598e32023-07-17 17:06:25 -07001507 BMCWEB_LOG_DEBUG(
1508 "DBUS response has more than 1 TPM Enable object:{}",
1509 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001510 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001511 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001512 return;
1513 }
1514
1515 // Make sure the Dbus response map has a service and objectPath
1516 // field
1517 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1518 {
Ed Tanous62598e32023-07-17 17:06:25 -07001519 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001520 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001521 return;
1522 }
1523
1524 const std::string& path = subtree[0].first;
1525 const std::string& serv = subtree[0].second.begin()->first;
1526
1527 if (serv.empty())
1528 {
Ed Tanous62598e32023-07-17 17:06:25 -07001529 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001530 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001531 return;
1532 }
1533
1534 // Valid TPM Enable object found, now setting the value
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001535 setDbusProperty(asyncResp, serv, path,
1536 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1537 "Boot/TrustedModuleRequiredToBoot", tpmRequired);
Patrick Williams5a39f772023-10-20 11:20:21 -05001538 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001539}
1540
1541/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301542 * @brief Sets boot properties into DBUS object(s).
1543 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001544 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001545 * @param[in] bootType The boot type to set.
1546 * @return Integer error code.
1547 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001548inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001549 const std::optional<std::string>& bootType)
1550{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001551 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001552
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001553 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001554 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001555 return;
1556 }
1557
1558 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001559 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001560 // Figure out which DBUS interface and property to use
1561 if (*bootType == "Legacy")
1562 {
1563 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1564 }
1565 else if (*bootType == "UEFI")
1566 {
1567 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1568 }
1569 else
1570 {
Ed Tanous62598e32023-07-17 17:06:25 -07001571 BMCWEB_LOG_DEBUG("Invalid property value for "
1572 "BootSourceOverrideMode: {}",
1573 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001574 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001575 "BootSourceOverrideMode");
1576 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001577 }
1578
1579 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001580 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001581
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001582 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1583 sdbusplus::message::object_path(
1584 "/xyz/openbmc_project/control/host0/boot"),
1585 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1586 "Boot/BootSourceOverrideMode", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001587}
1588
1589/**
1590 * @brief Sets boot properties into DBUS object(s).
1591 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001592 * @param[in] asyncResp Shared pointer for generating response
1593 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001594 * @param[in] bootType The boot type to set.
1595 * @return Integer error code.
1596 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001597inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001598 const std::optional<std::string>& bootEnable)
1599{
1600 if (!bootEnable)
1601 {
1602 return;
1603 }
1604 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001605 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001606
1607 bool bootOverrideEnable = false;
1608 bool bootOverridePersistent = false;
1609 // Figure out which DBUS interface and property to use
1610 if (*bootEnable == "Disabled")
1611 {
1612 bootOverrideEnable = false;
1613 }
1614 else if (*bootEnable == "Once")
1615 {
1616 bootOverrideEnable = true;
1617 bootOverridePersistent = false;
1618 }
1619 else if (*bootEnable == "Continuous")
1620 {
1621 bootOverrideEnable = true;
1622 bootOverridePersistent = true;
1623 }
1624 else
1625 {
Ed Tanous62598e32023-07-17 17:06:25 -07001626 BMCWEB_LOG_DEBUG(
1627 "Invalid property value for BootSourceOverrideEnabled: {}",
1628 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001629 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001630 "BootSourceOverrideEnabled");
1631 return;
1632 }
1633
1634 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001635 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001636
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001637 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1638 sdbusplus::message::object_path(
1639 "/xyz/openbmc_project/control/host0/boot"),
1640 "xyz.openbmc_project.Object.Enable", "Enabled",
1641 "Boot/BootSourceOverrideEnabled", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001642
1643 if (!bootOverrideEnable)
1644 {
1645 return;
1646 }
1647
1648 // In case boot override is enabled we need to set correct value for the
1649 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001650 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1651 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001652
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001653 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1654 sdbusplus::message::object_path(
1655 "/xyz/openbmc_project/control/host0/boot/one_time"),
1656 "xyz.openbmc_project.Object.Enable", "Enabled",
1657 "Boot/BootSourceOverrideEnabled", !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001658}
1659
1660/**
1661 * @brief Sets boot properties into DBUS object(s).
1662 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001663 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301664 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301665 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001666 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301667 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001668inline void
1669 setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1670 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301671{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001672 std::string bootSourceStr;
1673 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001674
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001675 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301676 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001677 return;
1678 }
1679
1680 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001681 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001682 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001683 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1684 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001685 {
Ed Tanous62598e32023-07-17 17:06:25 -07001686 BMCWEB_LOG_DEBUG(
1687 "Invalid property value for BootSourceOverrideTarget: {}",
1688 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001689 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690 "BootSourceTargetOverride");
1691 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001692 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301693
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001694 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001695 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1696 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001697
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001698 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1699 sdbusplus::message::object_path(
1700 "/xyz/openbmc_project/control/host0/boot"),
1701 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1702 "Boot/BootSourceOverrideTarget", bootSourceStr);
1703 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1704 sdbusplus::message::object_path(
1705 "/xyz/openbmc_project/control/host0/boot"),
1706 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1707 "Boot/BootSourceOverrideTarget", bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001708}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001709
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001710/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001711 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301712 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001713 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301714 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001715 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301716 * @param[in] bootEnable The boot override enable from incoming RF request.
1717 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001718 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301719 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001720
Ed Tanousac106bf2023-06-07 09:24:59 -07001721inline void
1722 setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1723 const std::optional<std::string>& bootSource,
1724 const std::optional<std::string>& bootType,
1725 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301726{
Ed Tanous62598e32023-07-17 17:06:25 -07001727 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301728
Ed Tanousac106bf2023-06-07 09:24:59 -07001729 setBootModeOrSource(asyncResp, bootSource);
1730 setBootType(asyncResp, bootType);
1731 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732}
1733
George Liuc6a620f2020-04-10 17:18:11 +08001734/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001735 * @brief Sets AssetTag
1736 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001737 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001738 * @param[in] assetTag "AssetTag" from request.
1739 *
1740 * @return None.
1741 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001742inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001743 const std::string& assetTag)
1744{
George Liue99073f2022-12-09 11:06:16 +08001745 constexpr std::array<std::string_view, 1> interfaces = {
1746 "xyz.openbmc_project.Inventory.Item.System"};
1747 dbus::utility::getSubTree(
1748 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001749 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001750 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001751 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001752 if (ec)
1753 {
Ed Tanous62598e32023-07-17 17:06:25 -07001754 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001755 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001756 return;
1757 }
1758 if (subtree.empty())
1759 {
Ed Tanous62598e32023-07-17 17:06:25 -07001760 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001761 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001762 return;
1763 }
1764 // Assume only 1 system D-Bus object
1765 // Throw an error if there is more than 1
1766 if (subtree.size() > 1)
1767 {
Ed Tanous62598e32023-07-17 17:06:25 -07001768 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001769 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001770 return;
1771 }
1772 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1773 {
Ed Tanous62598e32023-07-17 17:06:25 -07001774 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001775 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001776 return;
1777 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001778
Ed Tanous002d39b2022-05-31 08:59:27 -07001779 const std::string& path = subtree[0].first;
1780 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001781
Ed Tanous002d39b2022-05-31 08:59:27 -07001782 if (service.empty())
1783 {
Ed Tanous62598e32023-07-17 17:06:25 -07001784 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001785 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001786 return;
1787 }
1788
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001789 setDbusProperty(asyncResp, service, path,
1790 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1791 "AssetTag", "AssetTag", assetTag);
Patrick Williams5a39f772023-10-20 11:20:21 -05001792 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001793}
1794
1795/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001796 * @brief Validate the specified stopBootOnFault is valid and return the
1797 * stopBootOnFault name associated with that string
1798 *
1799 * @param[in] stopBootOnFaultString String representing the desired
1800 * stopBootOnFault
1801 *
1802 * @return stopBootOnFault value or empty if incoming value is not valid
1803 */
1804inline std::optional<bool>
1805 validstopBootOnFault(const std::string& stopBootOnFaultString)
1806{
1807 if (stopBootOnFaultString == "AnyFault")
1808 {
1809 return true;
1810 }
1811
1812 if (stopBootOnFaultString == "Never")
1813 {
1814 return false;
1815 }
1816
1817 return std::nullopt;
1818}
1819
1820/**
1821 * @brief Sets stopBootOnFault
1822 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001823 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001824 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1825 *
1826 * @return None.
1827 */
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001828inline void
1829 setStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1830 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001831{
Ed Tanous62598e32023-07-17 17:06:25 -07001832 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001833
1834 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1835 if (!stopBootEnabled)
1836 {
Ed Tanous62598e32023-07-17 17:06:25 -07001837 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1838 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001839 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001840 "StopBootOnFault");
1841 return;
1842 }
1843
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001844 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1845 sdbusplus::message::object_path(
1846 "/xyz/openbmc_project/logging/settings"),
1847 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1848 "Boot/StopBootOnFault", *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001849}
1850
1851/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001852 * @brief Sets automaticRetry (Auto Reboot)
1853 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001854 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001855 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1856 *
1857 * @return None.
1858 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001859inline void
1860 setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1861 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001862{
Ed Tanous62598e32023-07-17 17:06:25 -07001863 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001864
1865 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001866 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001867
1868 if (automaticRetryConfig == "Disabled")
1869 {
1870 autoRebootEnabled = false;
1871 }
1872 else if (automaticRetryConfig == "RetryAttempts")
1873 {
1874 autoRebootEnabled = true;
1875 }
1876 else
1877 {
Ed Tanous62598e32023-07-17 17:06:25 -07001878 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1879 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001880 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001881 "AutomaticRetryConfig");
1882 return;
1883 }
1884
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001885 setDbusProperty(asyncResp, "xyz.openbmc_project.Settings",
1886 sdbusplus::message::object_path(
1887 "/xyz/openbmc_project/control/host0/auto_reboot"),
1888 "xyz.openbmc_project.Control.Boot.RebootPolicy",
1889 "AutoReboot", "Boot/AutomaticRetryConfig",
1890 autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001891}
1892
Ed Tanous8d69c662023-06-21 10:29:06 -07001893inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1894{
1895 if (policy == "AlwaysOn")
1896 {
1897 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1898 }
1899 if (policy == "AlwaysOff")
1900 {
1901 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1902 }
1903 if (policy == "LastState")
1904 {
1905 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1906 }
1907 return "";
1908}
1909
Gunnar Mills69f35302020-05-17 16:06:31 -05001910/**
George Liuc6a620f2020-04-10 17:18:11 +08001911 * @brief Sets power restore policy properties.
1912 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001913 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001914 * @param[in] policy power restore policy properties from request.
1915 *
1916 * @return None.
1917 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001918inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001919 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous8d69c662023-06-21 10:29:06 -07001920 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001921{
Ed Tanous62598e32023-07-17 17:06:25 -07001922 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001923
Ed Tanous8d69c662023-06-21 10:29:06 -07001924 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001925
Ed Tanous8d69c662023-06-21 10:29:06 -07001926 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001927 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001928 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001929 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001930 return;
1931 }
1932
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001933 setDbusProperty(
1934 asyncResp, "xyz.openbmc_project.Settings",
1935 sdbusplus::message::object_path(
1936 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001937 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001938 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001939}
1940
AppaRao Pulia6349912019-10-18 17:16:08 +05301941/**
1942 * @brief Retrieves provisioning status
1943 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001944 * @param[in] asyncResp Shared pointer for completing asynchronous
1945 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301946 *
1947 * @return None.
1948 */
Ed Tanous25b54db2024-04-17 15:40:31 -07001949inline void
1950 getProvisioningStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301951{
Ed Tanous62598e32023-07-17 17:06:25 -07001952 BMCWEB_LOG_DEBUG("Get OEM information.");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001953 sdbusplus::asio::getAllProperties(
1954 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1955 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001956 [asyncResp](const boost::system::error_code& ec,
1957 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001958 nlohmann::json& oemPFR =
Ed Tanousac106bf2023-06-07 09:24:59 -07001959 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1960 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001961 "#OemComputerSystem.OpenBmc";
1962 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001963
Ed Tanous002d39b2022-05-31 08:59:27 -07001964 if (ec)
1965 {
Ed Tanous62598e32023-07-17 17:06:25 -07001966 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001967 // not an error, don't have to have the interface
1968 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1969 return;
1970 }
1971
1972 const bool* provState = nullptr;
1973 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001974
1975 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001976 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1977 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001978
1979 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001980 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001981 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001982 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001983 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301984
Ed Tanous002d39b2022-05-31 08:59:27 -07001985 if ((provState == nullptr) || (lockState == nullptr))
1986 {
Ed Tanous62598e32023-07-17 17:06:25 -07001987 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
Ed Tanousac106bf2023-06-07 09:24:59 -07001988 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001989 return;
1990 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301991
Ed Tanous25b54db2024-04-17 15:40:31 -07001992 if (*provState)
Ed Tanous002d39b2022-05-31 08:59:27 -07001993 {
Ed Tanous25b54db2024-04-17 15:40:31 -07001994 if (*lockState)
AppaRao Pulia6349912019-10-18 17:16:08 +05301995 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001996 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301997 }
1998 else
1999 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002000 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302001 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002002 }
2003 else
2004 {
2005 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2006 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002007 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302008}
AppaRao Pulia6349912019-10-18 17:16:08 +05302009
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302010/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002011 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002012 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002013 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002014 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002015 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002016 */
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002017inline computer_system::PowerMode
2018 translatePowerModeString(const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002019{
Chris Cainb6655102024-02-01 14:35:33 -06002020 using PowerMode = computer_system::PowerMode;
2021
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002022 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002023 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002024 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002025 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002026 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002027 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002028 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002029 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002030 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002031 if (modeString ==
2032 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002033 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002034 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002035 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002036 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002037 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2038 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002039 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002040 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002041 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002042 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2043 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002044 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002045 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002046 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002047 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2048 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002049 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002050 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002051 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002052 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002053 return PowerMode::OEM;
2054 }
2055 // Any other values would be invalid
2056 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2057 return PowerMode::Invalid;
2058}
2059
2060inline void
2061 afterGetPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2062 const boost::system::error_code& ec,
2063 const dbus::utility::DBusPropertiesMap& properties)
2064{
2065 if (ec)
2066 {
2067 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2068 messages::internalError(asyncResp->res);
2069 return;
2070 }
2071
2072 std::string powerMode;
2073 const std::vector<std::string>* allowedModes = nullptr;
2074 const bool success = sdbusplus::unpackPropertiesNoThrow(
2075 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2076 "AllowedPowerModes", allowedModes);
2077
2078 if (!success)
2079 {
2080 messages::internalError(asyncResp->res);
2081 return;
2082 }
2083
2084 nlohmann::json::array_t modeList;
2085 if (allowedModes == nullptr)
2086 {
2087 modeList.emplace_back("Static");
2088 modeList.emplace_back("MaximumPerformance");
2089 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002090 }
2091 else
2092 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002093 for (const auto& aMode : *allowedModes)
2094 {
2095 computer_system::PowerMode modeValue =
2096 translatePowerModeString(aMode);
2097 if (modeValue == computer_system::PowerMode::Invalid)
2098 {
2099 messages::internalError(asyncResp->res);
2100 continue;
2101 }
2102 modeList.emplace_back(modeValue);
2103 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002104 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002105 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002106
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002107 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2108 const computer_system::PowerMode modeValue =
2109 translatePowerModeString(powerMode);
2110 if (modeValue == computer_system::PowerMode::Invalid)
2111 {
2112 messages::internalError(asyncResp->res);
2113 return;
2114 }
2115 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2116}
Chris Cain3a2d04242021-05-28 16:57:10 -05002117/**
2118 * @brief Retrieves system power mode
2119 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002120 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002121 *
2122 * @return None.
2123 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002124inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002125{
Ed Tanous62598e32023-07-17 17:06:25 -07002126 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002127
2128 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002129 constexpr std::array<std::string_view, 1> interfaces = {
2130 "xyz.openbmc_project.Control.Power.Mode"};
2131 dbus::utility::getSubTree(
2132 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002133 [asyncResp](const boost::system::error_code& ec,
2134 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002135 if (ec)
2136 {
Ed Tanous62598e32023-07-17 17:06:25 -07002137 BMCWEB_LOG_DEBUG("DBUS response error on Power.Mode GetSubTree {}",
2138 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002139 // This is an optional D-Bus object so just return if
2140 // error occurs
2141 return;
2142 }
2143 if (subtree.empty())
2144 {
2145 // As noted above, this is an optional interface so just return
2146 // if there is no instance found
2147 return;
2148 }
2149 if (subtree.size() > 1)
2150 {
2151 // More then one PowerMode object is not supported and is an
2152 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002153 BMCWEB_LOG_DEBUG(
2154 "Found more than 1 system D-Bus Power.Mode objects: {}",
2155 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002156 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002157 return;
2158 }
2159 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2160 {
Ed Tanous62598e32023-07-17 17:06:25 -07002161 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002162 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002163 return;
2164 }
2165 const std::string& path = subtree[0].first;
2166 const std::string& service = subtree[0].second.begin()->first;
2167 if (service.empty())
2168 {
Ed Tanous62598e32023-07-17 17:06:25 -07002169 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002170 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002171 return;
2172 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002173
2174 // Valid Power Mode object found, now read the mode properties
2175 sdbusplus::asio::getAllProperties(
Ed Tanous002d39b2022-05-31 08:59:27 -07002176 *crow::connections::systemBus, service, path,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002177 "xyz.openbmc_project.Control.Power.Mode",
Ed Tanousac106bf2023-06-07 09:24:59 -07002178 [asyncResp](const boost::system::error_code& ec2,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002179 const dbus::utility::DBusPropertiesMap& properties) {
2180 afterGetPowerMode(asyncResp, ec2, properties);
George Liue99073f2022-12-09 11:06:16 +08002181 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002182 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002183}
2184
2185/**
2186 * @brief Validate the specified mode is valid and return the PowerMode
2187 * name associated with that string
2188 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002189 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002190 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002191 *
2192 * @return PowerMode value or empty string if mode is not valid
2193 */
2194inline std::string
Ed Tanousac106bf2023-06-07 09:24:59 -07002195 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cainb6655102024-02-01 14:35:33 -06002196 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002197{
Chris Cainb6655102024-02-01 14:35:33 -06002198 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002199 std::string mode;
2200
Chris Cainb6655102024-02-01 14:35:33 -06002201 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002202 {
2203 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2204 }
Chris Cainb6655102024-02-01 14:35:33 -06002205 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002206 {
George Liu0fda0f12021-11-16 10:06:17 +08002207 mode =
2208 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002209 }
Chris Cainb6655102024-02-01 14:35:33 -06002210 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002211 {
2212 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2213 }
Chris Cainb6655102024-02-01 14:35:33 -06002214 else if (modeValue == PowerMode::BalancedPerformance)
2215 {
2216 mode =
2217 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2218 }
2219 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2220 {
2221 mode =
2222 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2223 }
2224 else if (modeValue == PowerMode::EfficiencyFavorPower)
2225 {
2226 mode =
2227 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2228 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002229 else
2230 {
Chris Cainb6655102024-02-01 14:35:33 -06002231 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002232 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002233 }
2234 return mode;
2235}
2236
2237/**
2238 * @brief Sets system power mode.
2239 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002240 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002241 * @param[in] pmode System power mode from request.
2242 *
2243 * @return None.
2244 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002245inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002246 const std::string& pmode)
2247{
Ed Tanous62598e32023-07-17 17:06:25 -07002248 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002249
Ed Tanousac106bf2023-06-07 09:24:59 -07002250 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002251 if (powerMode.empty())
2252 {
2253 return;
2254 }
2255
2256 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002257 constexpr std::array<std::string_view, 1> interfaces = {
2258 "xyz.openbmc_project.Control.Power.Mode"};
2259 dbus::utility::getSubTree(
2260 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002261 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002262 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002263 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002264 if (ec)
2265 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002266 BMCWEB_LOG_ERROR("DBUS response error on Power.Mode GetSubTree {}",
Ed Tanous62598e32023-07-17 17:06:25 -07002267 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002268 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002269 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002270 return;
2271 }
2272 if (subtree.empty())
2273 {
2274 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002275 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002276 "PowerMode");
2277 return;
2278 }
2279 if (subtree.size() > 1)
2280 {
2281 // More then one PowerMode object is not supported and is an
2282 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002283 BMCWEB_LOG_DEBUG(
2284 "Found more than 1 system D-Bus Power.Mode objects: {}",
2285 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002286 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002287 return;
2288 }
2289 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2290 {
Ed Tanous62598e32023-07-17 17:06:25 -07002291 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002292 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002293 return;
2294 }
2295 const std::string& path = subtree[0].first;
2296 const std::string& service = subtree[0].second.begin()->first;
2297 if (service.empty())
2298 {
Ed Tanous62598e32023-07-17 17:06:25 -07002299 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002300 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002301 return;
2302 }
2303
Ed Tanous62598e32023-07-17 17:06:25 -07002304 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002305
2306 // Set the Power Mode property
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002307 setDbusProperty(asyncResp, service, path,
2308 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2309 "PowerMode", powerMode);
Patrick Williams5a39f772023-10-20 11:20:21 -05002310 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002311}
2312
2313/**
Yong Li51709ff2019-09-30 14:13:04 +08002314 * @brief Translates watchdog timeout action DBUS property value to redfish.
2315 *
2316 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2317 *
2318 * @return Returns as a string, the timeout action in Redfish terms. If
2319 * translation cannot be done, returns an empty string.
2320 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002321inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002322{
2323 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2324 {
2325 return "None";
2326 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002327 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002328 {
2329 return "ResetSystem";
2330 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002331 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002332 {
2333 return "PowerDown";
2334 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002335 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002336 {
2337 return "PowerCycle";
2338 }
2339
2340 return "";
2341}
2342
2343/**
Yong Lic45f0082019-10-10 14:19:01 +08002344 *@brief Translates timeout action from Redfish to DBUS property value.
2345 *
2346 *@param[in] rfAction The timeout action in Redfish.
2347 *
2348 *@return Returns as a string, the time_out action as expected by DBUS.
2349 *If translation cannot be done, returns an empty string.
2350 */
2351
Ed Tanous23a21a12020-07-25 04:45:05 +00002352inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002353{
2354 if (rfAction == "None")
2355 {
2356 return "xyz.openbmc_project.State.Watchdog.Action.None";
2357 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002358 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002359 {
2360 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2361 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002362 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002363 {
2364 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2365 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002366 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002367 {
2368 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2369 }
2370
2371 return "";
2372}
2373
2374/**
Yong Li51709ff2019-09-30 14:13:04 +08002375 * @brief Retrieves host watchdog timer properties over DBUS
2376 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002377 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002378 *
2379 * @return None.
2380 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002381inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002382 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002383{
Ed Tanous62598e32023-07-17 17:06:25 -07002384 BMCWEB_LOG_DEBUG("Get host watchodg");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002385 sdbusplus::asio::getAllProperties(
2386 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2387 "/xyz/openbmc_project/watchdog/host0",
2388 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002389 [asyncResp](const boost::system::error_code& ec,
2390 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002391 if (ec)
2392 {
2393 // watchdog service is stopped
Ed Tanous62598e32023-07-17 17:06:25 -07002394 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002395 return;
2396 }
2397
Ed Tanous62598e32023-07-17 17:06:25 -07002398 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002399
2400 nlohmann::json& hostWatchdogTimer =
Ed Tanousac106bf2023-06-07 09:24:59 -07002401 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002402
2403 // watchdog service is running/enabled
2404 hostWatchdogTimer["Status"]["State"] = "Enabled";
2405
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002406 const bool* enabled = nullptr;
2407 const std::string* expireAction = nullptr;
2408
2409 const bool success = sdbusplus::unpackPropertiesNoThrow(
2410 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2411 "ExpireAction", expireAction);
2412
2413 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002414 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002415 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002416 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002417 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002418
2419 if (enabled != nullptr)
2420 {
2421 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2422 }
2423
2424 if (expireAction != nullptr)
2425 {
2426 std::string action = dbusToRfWatchdogAction(*expireAction);
2427 if (action.empty())
2428 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002429 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002430 return;
2431 }
2432 hostWatchdogTimer["TimeoutAction"] = action;
2433 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002434 });
Yong Li51709ff2019-09-30 14:13:04 +08002435}
2436
2437/**
Yong Lic45f0082019-10-10 14:19:01 +08002438 * @brief Sets Host WatchDog Timer properties.
2439 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002440 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002441 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2442 * RF request.
2443 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2444 *
2445 * @return None.
2446 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002447inline void
2448 setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2449 const std::optional<bool> wdtEnable,
2450 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002451{
Ed Tanous62598e32023-07-17 17:06:25 -07002452 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002453
2454 if (wdtTimeOutAction)
2455 {
2456 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2457 // check if TimeOut Action is Valid
2458 if (wdtTimeOutActStr.empty())
2459 {
Ed Tanous62598e32023-07-17 17:06:25 -07002460 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2461 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002462 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002463 "TimeoutAction");
2464 return;
2465 }
2466
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002467 setDbusProperty(asyncResp, "xyz.openbmc_project.Watchdog",
2468 sdbusplus::message::object_path(
2469 "/xyz/openbmc_project/watchdog/host0"),
2470 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2471 "HostWatchdogTimer/TimeoutAction", wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002472 }
2473
2474 if (wdtEnable)
2475 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002476 setDbusProperty(asyncResp, "xyz.openbmc_project.Watchdog",
2477 sdbusplus::message::object_path(
2478 "/xyz/openbmc_project/watchdog/host0"),
2479 "xyz.openbmc_project.State.Watchdog", "Enabled",
2480 "HostWatchdogTimer/FunctionEnabled", *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002481 }
2482}
2483
Chris Cain37bbf982021-09-20 10:53:09 -05002484/**
2485 * @brief Parse the Idle Power Saver properties into json
2486 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002487 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002488 * @param[in] properties IPS property data from DBus.
2489 *
2490 * @return true if successful
2491 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002492inline bool
Ed Tanousac106bf2023-06-07 09:24:59 -07002493 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002494 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002495{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002496 const bool* enabled = nullptr;
2497 const uint8_t* enterUtilizationPercent = nullptr;
2498 const uint64_t* enterDwellTime = nullptr;
2499 const uint8_t* exitUtilizationPercent = nullptr;
2500 const uint64_t* exitDwellTime = nullptr;
2501
2502 const bool success = sdbusplus::unpackPropertiesNoThrow(
2503 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002504 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2505 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2506 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002507
2508 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002509 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002510 return false;
2511 }
2512
2513 if (enabled != nullptr)
2514 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002515 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002516 }
2517
2518 if (enterUtilizationPercent != nullptr)
2519 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002520 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002521 *enterUtilizationPercent;
2522 }
2523
2524 if (enterDwellTime != nullptr)
2525 {
2526 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002527 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002528 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2529 .count();
2530 }
2531
2532 if (exitUtilizationPercent != nullptr)
2533 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002534 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002535 *exitUtilizationPercent;
2536 }
2537
2538 if (exitDwellTime != nullptr)
2539 {
2540 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002541 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002542 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2543 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002544 }
2545
2546 return true;
2547}
2548
2549/**
2550 * @brief Retrieves host watchdog timer properties over DBUS
2551 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002552 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002553 *
2554 * @return None.
2555 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002556inline void
2557 getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002558{
Ed Tanous62598e32023-07-17 17:06:25 -07002559 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002560
2561 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002562 constexpr std::array<std::string_view, 1> interfaces = {
2563 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2564 dbus::utility::getSubTree(
2565 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002566 [asyncResp](const boost::system::error_code& ec,
2567 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002568 if (ec)
2569 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002570 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002571 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2572 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002573 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002574 return;
2575 }
2576 if (subtree.empty())
2577 {
2578 // This is an optional interface so just return
2579 // if there is no instance found
Ed Tanous62598e32023-07-17 17:06:25 -07002580 BMCWEB_LOG_DEBUG("No instances found");
Ed Tanous002d39b2022-05-31 08:59:27 -07002581 return;
2582 }
2583 if (subtree.size() > 1)
2584 {
2585 // More then one PowerIdlePowerSaver object is not supported and
2586 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002587 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2588 "Power.IdlePowerSaver objects: {}",
2589 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002590 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002591 return;
2592 }
2593 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2594 {
Ed Tanous62598e32023-07-17 17:06:25 -07002595 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002596 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002597 return;
2598 }
2599 const std::string& path = subtree[0].first;
2600 const std::string& service = subtree[0].second.begin()->first;
2601 if (service.empty())
2602 {
Ed Tanous62598e32023-07-17 17:06:25 -07002603 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002604 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002605 return;
2606 }
2607
2608 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002609 sdbusplus::asio::getAllProperties(
2610 *crow::connections::systemBus, service, path,
2611 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanousac106bf2023-06-07 09:24:59 -07002612 [asyncResp](const boost::system::error_code& ec2,
2613 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002614 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002615 {
Ed Tanous62598e32023-07-17 17:06:25 -07002616 BMCWEB_LOG_ERROR(
2617 "DBUS response error on IdlePowerSaver GetAll: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002618 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002619 return;
2620 }
2621
Ed Tanousac106bf2023-06-07 09:24:59 -07002622 if (!parseIpsProperties(asyncResp, properties))
Ed Tanous002d39b2022-05-31 08:59:27 -07002623 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002624 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002625 return;
2626 }
George Liue99073f2022-12-09 11:06:16 +08002627 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002628 });
Chris Cain37bbf982021-09-20 10:53:09 -05002629
Ed Tanous62598e32023-07-17 17:06:25 -07002630 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002631}
2632
2633/**
2634 * @brief Sets Idle Power Saver properties.
2635 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002636 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002637 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2638 * RF request.
2639 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2640 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2641 * before entering idle state.
2642 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2643 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2644 * before exiting idle state
2645 *
2646 * @return None.
2647 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002648inline void
2649 setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2650 const std::optional<bool> ipsEnable,
2651 const std::optional<uint8_t> ipsEnterUtil,
2652 const std::optional<uint64_t> ipsEnterTime,
2653 const std::optional<uint8_t> ipsExitUtil,
2654 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002655{
Ed Tanous62598e32023-07-17 17:06:25 -07002656 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002657
2658 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002659 constexpr std::array<std::string_view, 1> interfaces = {
2660 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2661 dbus::utility::getSubTree(
2662 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002663 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002664 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002665 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002666 if (ec)
2667 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002668 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002669 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2670 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002671 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002672 return;
2673 }
2674 if (subtree.empty())
2675 {
2676 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002677 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002678 "IdlePowerSaver");
2679 return;
2680 }
2681 if (subtree.size() > 1)
2682 {
2683 // More then one PowerIdlePowerSaver object is not supported and
2684 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002685 BMCWEB_LOG_DEBUG(
2686 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2687 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002688 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002689 return;
2690 }
2691 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2692 {
Ed Tanous62598e32023-07-17 17:06:25 -07002693 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002694 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002695 return;
2696 }
2697 const std::string& path = subtree[0].first;
2698 const std::string& service = subtree[0].second.begin()->first;
2699 if (service.empty())
2700 {
Ed Tanous62598e32023-07-17 17:06:25 -07002701 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002702 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002703 return;
2704 }
Chris Cain37bbf982021-09-20 10:53:09 -05002705
Ed Tanous002d39b2022-05-31 08:59:27 -07002706 // Valid Power IdlePowerSaver object found, now set any values that
2707 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002708
Ed Tanous002d39b2022-05-31 08:59:27 -07002709 if (ipsEnable)
2710 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002711 setDbusProperty(asyncResp, service, path,
2712 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2713 "Enabled", "IdlePowerSaver/Enabled", *ipsEnable);
Ed Tanous002d39b2022-05-31 08:59:27 -07002714 }
2715 if (ipsEnterUtil)
2716 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002717 setDbusProperty(asyncResp, service, path,
2718 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2719 "EnterUtilizationPercent",
2720 "IdlePowerSaver/EnterUtilizationPercent",
2721 *ipsEnterUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002722 }
2723 if (ipsEnterTime)
2724 {
2725 // Convert from seconds into milliseconds for DBus
2726 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002727 setDbusProperty(asyncResp, service, path,
2728 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2729 "EnterDwellTime",
2730 "IdlePowerSaver/EnterDwellTimeSeconds",
2731 timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002732 }
2733 if (ipsExitUtil)
2734 {
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002735 setDbusProperty(asyncResp, service, path,
2736 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2737 "ExitUtilizationPercent",
2738 "IdlePowerSaver/ExitUtilizationPercent",
2739 *ipsExitUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002740 }
2741 if (ipsExitTime)
2742 {
2743 // Convert from seconds into milliseconds for DBus
2744 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002745 setDbusProperty(asyncResp, service, path,
2746 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2747 "ExitDwellTime",
2748 "IdlePowerSaver/ExitDwellTimeSeconds",
2749 timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002750 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002751 });
Chris Cain37bbf982021-09-20 10:53:09 -05002752
Ed Tanous62598e32023-07-17 17:06:25 -07002753 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002754}
2755
Ed Tanousc1e219d2023-06-07 10:34:33 -07002756inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002757 crow::App& app, const crow::Request& req,
2758 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2759{
2760 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2761 {
2762 return;
2763 }
2764 asyncResp->res.addHeader(
2765 boost::beast::http::field::link,
2766 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2767}
2768
Ed Tanousc1e219d2023-06-07 10:34:33 -07002769inline void handleComputerSystemCollectionGet(
2770 crow::App& app, const crow::Request& req,
2771 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2772{
2773 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2774 {
2775 return;
2776 }
2777
2778 asyncResp->res.addHeader(
2779 boost::beast::http::field::link,
2780 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2781 asyncResp->res.jsonValue["@odata.type"] =
2782 "#ComputerSystemCollection.ComputerSystemCollection";
2783 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2784 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2785
2786 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2787 ifaceArray = nlohmann::json::array();
Ed Tanous25b54db2024-04-17 15:40:31 -07002788 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002789 {
2790 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2791 // Option currently returns no systems. TBD
2792 return;
2793 }
2794 asyncResp->res.jsonValue["Members@odata.count"] = 1;
2795 nlohmann::json::object_t system;
Ed Tanous253f11b2024-05-16 09:38:31 -07002796 system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
2797 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002798 ifaceArray.emplace_back(std::move(system));
2799 sdbusplus::asio::getProperty<std::string>(
2800 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2801 "/xyz/openbmc_project/network/hypervisor",
2802 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
2803 [asyncResp](const boost::system::error_code& ec2,
2804 const std::string& /*hostName*/) {
2805 if (ec2)
2806 {
2807 return;
2808 }
2809 auto val = asyncResp->res.jsonValue.find("Members@odata.count");
2810 if (val == asyncResp->res.jsonValue.end())
2811 {
Ed Tanous62598e32023-07-17 17:06:25 -07002812 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002813 return;
2814 }
2815 uint64_t* count = val->get_ptr<uint64_t*>();
2816 if (count == nullptr)
2817 {
Ed Tanous62598e32023-07-17 17:06:25 -07002818 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002819 return;
2820 }
2821 *count = *count + 1;
Ed Tanous62598e32023-07-17 17:06:25 -07002822 BMCWEB_LOG_DEBUG("Hypervisor is available");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002823 nlohmann::json& ifaceArray2 = asyncResp->res.jsonValue["Members"];
2824 nlohmann::json::object_t hypervisor;
2825 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2826 ifaceArray2.emplace_back(std::move(hypervisor));
Patrick Williams5a39f772023-10-20 11:20:21 -05002827 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07002828}
2829
Yong Lic45f0082019-10-10 14:19:01 +08002830/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 * Function transceives data with dbus directly.
2832 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002833inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002834{
Patrick Williams89492a12023-05-10 07:51:34 -05002835 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2836 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2837 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002838 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002839 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002840
2841 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002842 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002843 if (ec)
2844 {
Ed Tanous62598e32023-07-17 17:06:25 -07002845 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002846 messages::internalError(asyncResp->res);
2847 return;
2848 }
2849 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05002850 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002851 serviceName, objectPath, interfaceName, method);
2852}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002853
Ed Tanousc1e219d2023-06-07 10:34:33 -07002854inline void handleComputerSystemResetActionPost(
2855 crow::App& app, const crow::Request& req,
2856 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2857 const std::string& systemName)
2858{
2859 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2860 {
2861 return;
2862 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002863 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002864 {
2865 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2866 systemName);
2867 return;
2868 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002869 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002870 {
2871 // Option currently returns no systems. TBD
2872 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2873 systemName);
2874 return;
2875 }
2876 std::string resetType;
2877 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2878 {
2879 return;
2880 }
2881
2882 // Get the command and host vs. chassis
2883 std::string command;
2884 bool hostCommand = true;
2885 if ((resetType == "On") || (resetType == "ForceOn"))
2886 {
2887 command = "xyz.openbmc_project.State.Host.Transition.On";
2888 hostCommand = true;
2889 }
2890 else if (resetType == "ForceOff")
2891 {
2892 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2893 hostCommand = false;
2894 }
2895 else if (resetType == "ForceRestart")
2896 {
2897 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2898 hostCommand = true;
2899 }
2900 else if (resetType == "GracefulShutdown")
2901 {
2902 command = "xyz.openbmc_project.State.Host.Transition.Off";
2903 hostCommand = true;
2904 }
2905 else if (resetType == "GracefulRestart")
2906 {
2907 command =
2908 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2909 hostCommand = true;
2910 }
2911 else if (resetType == "PowerCycle")
2912 {
2913 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2914 hostCommand = true;
2915 }
2916 else if (resetType == "Nmi")
2917 {
2918 doNMI(asyncResp);
2919 return;
2920 }
2921 else
2922 {
2923 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2924 return;
2925 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002926 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002927
2928 if (hostCommand)
2929 {
Ed Tanousd02aad32024-02-13 14:43:34 -08002930 setDbusProperty(asyncResp, "xyz.openbmc_project.State.Host",
2931 statePath / "host0", "xyz.openbmc_project.State.Host",
2932 "RequestedHostTransition", "Reset", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002933 }
2934 else
2935 {
Ed Tanousd02aad32024-02-13 14:43:34 -08002936 setDbusProperty(asyncResp, "xyz.openbmc_project.State.Chassis",
2937 statePath / "chassis0",
2938 "xyz.openbmc_project.State.Chassis",
2939 "RequestedPowerTransition", "Reset", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002940 }
2941}
2942
Ed Tanousc1e219d2023-06-07 10:34:33 -07002943inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002944 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002945 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2946 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002947{
2948 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2949 {
2950 return;
2951 }
2952
2953 asyncResp->res.addHeader(
2954 boost::beast::http::field::link,
2955 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2956}
2957
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002958inline void afterPortRequest(
2959 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2960 const boost::system::error_code& ec,
2961 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2962{
2963 if (ec)
2964 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002965 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002966 messages::internalError(asyncResp->res);
2967 return;
2968 }
2969 for (const auto& data : socketData)
2970 {
2971 const std::string& socketPath = get<0>(data);
2972 const std::string& protocolName = get<1>(data);
2973 bool isProtocolEnabled = get<2>(data);
2974 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2975 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2976 // need to retrieve port number for
2977 // obmc-console-ssh service
2978 if (protocolName == "SSH")
2979 {
2980 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002981 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002982 int portNumber) {
2983 if (ec1)
2984 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002985 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002986 messages::internalError(asyncResp->res);
2987 return;
2988 }
2989 nlohmann::json& dataJson1 =
2990 asyncResp->res.jsonValue["SerialConsole"];
2991 dataJson1[protocolName]["Port"] = portNumber;
2992 });
2993 }
2994 }
2995}
Ed Tanousc1e219d2023-06-07 10:34:33 -07002996
2997inline void
2998 handleComputerSystemGet(crow::App& app, const crow::Request& req,
2999 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3000 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003001{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003002 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3003 {
3004 return;
3005 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003006
Ed Tanous25b54db2024-04-17 15:40:31 -07003007 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003008 {
3009 // Option currently returns no systems. TBD
3010 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3011 systemName);
3012 return;
3013 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003014
Ed Tanousc1e219d2023-06-07 10:34:33 -07003015 if (systemName == "hypervisor")
3016 {
3017 handleHypervisorSystemGet(asyncResp);
3018 return;
3019 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003020
Ed Tanous253f11b2024-05-16 09:38:31 -07003021 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003022 {
3023 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3024 systemName);
3025 return;
3026 }
3027 asyncResp->res.addHeader(
3028 boost::beast::http::field::link,
3029 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3030 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003031 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003032 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3033 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003034 asyncResp->res.jsonValue["SystemType"] = "Physical";
3035 asyncResp->res.jsonValue["Description"] = "Computer System";
3036 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003037 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003038 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003039 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3040 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003041
Ed Tanous253f11b2024-05-16 09:38:31 -07003042 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3043 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3044 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3045 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3046 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3047 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003048 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003049 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3050 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003051
Ed Tanousc1e219d2023-06-07 10:34:33 -07003052 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003053 boost::urls::format(
3054 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3055 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003056 asyncResp->res
3057 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003058 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3059 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003060
Ed Tanous253f11b2024-05-16 09:38:31 -07003061 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3062 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3063 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3064 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003065
Ed Tanousc1e219d2023-06-07 10:34:33 -07003066 nlohmann::json::array_t managedBy;
3067 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003068 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3069 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003070 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3071 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3072 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003073
Ed Tanousc1e219d2023-06-07 10:34:33 -07003074 // Fill in SerialConsole info
3075 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3076 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003077
Ed Tanousc1e219d2023-06-07 10:34:33 -07003078 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3079 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3080 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3081 "Press ~. to exit console";
3082 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3083 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003084
Ed Tanous25b54db2024-04-17 15:40:31 -07003085 if constexpr (BMCWEB_KVM)
3086 {
3087 // Fill in GraphicalConsole info
3088 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3089 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3090 4;
3091 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3092 nlohmann::json::array_t({"KVMIP"});
3093 }
James Feistb49ac872019-05-21 15:12:01 -07003094
Ed Tanousc1e219d2023-06-07 10:34:33 -07003095 getMainChassisId(asyncResp,
3096 [](const std::string& chassisId,
3097 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3098 nlohmann::json::array_t chassisArray;
3099 nlohmann::json& chassis = chassisArray.emplace_back();
3100 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3101 chassisId);
3102 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3103 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003104
George Liu59a17e42022-10-08 09:27:47 +08003105 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003106 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3107 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003108 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003109 getHostState(asyncResp);
3110 getBootProperties(asyncResp);
3111 getBootProgress(asyncResp);
3112 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003113 pcie_util::getPCIeDeviceList(asyncResp,
3114 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003115 getHostWatchdogTimer(asyncResp);
3116 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003117 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003118 getAutomaticRetryPolicy(asyncResp);
3119 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003120 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3121 {
3122 getProvisioningStatus(asyncResp);
3123 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003124 getTrustedModuleRequiredToBoot(asyncResp);
3125 getPowerMode(asyncResp);
3126 getIdlePowerSaver(asyncResp);
3127}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003128
Ed Tanousc1e219d2023-06-07 10:34:33 -07003129inline void handleComputerSystemPatch(
3130 crow::App& app, const crow::Request& req,
3131 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3132 const std::string& systemName)
3133{
3134 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3135 {
3136 return;
3137 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003138 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003139 {
3140 // Option currently returns no systems. TBD
3141 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3142 systemName);
3143 return;
3144 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003145 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003146 {
3147 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3148 systemName);
3149 return;
3150 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003151
Ed Tanousc1e219d2023-06-07 10:34:33 -07003152 asyncResp->res.addHeader(
3153 boost::beast::http::field::link,
3154 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003155
Ed Tanousc1e219d2023-06-07 10:34:33 -07003156 std::optional<bool> locationIndicatorActive;
3157 std::optional<std::string> indicatorLed;
3158 std::optional<std::string> assetTag;
3159 std::optional<std::string> powerRestorePolicy;
3160 std::optional<std::string> powerMode;
3161 std::optional<bool> wdtEnable;
3162 std::optional<std::string> wdtTimeOutAction;
3163 std::optional<std::string> bootSource;
3164 std::optional<std::string> bootType;
3165 std::optional<std::string> bootEnable;
3166 std::optional<std::string> bootAutomaticRetry;
3167 std::optional<uint32_t> bootAutomaticRetryAttempts;
3168 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003169 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003170 std::optional<bool> ipsEnable;
3171 std::optional<uint8_t> ipsEnterUtil;
3172 std::optional<uint64_t> ipsEnterTime;
3173 std::optional<uint8_t> ipsExitUtil;
3174 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003175
Ed Tanousc1e219d2023-06-07 10:34:33 -07003176 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003177 if (!json_util::readJsonPatch(
3178 req, asyncResp->res,
3179 "IndicatorLED", indicatorLed,
3180 "LocationIndicatorActive", locationIndicatorActive,
3181 "AssetTag", assetTag,
3182 "PowerRestorePolicy", powerRestorePolicy,
3183 "PowerMode", powerMode,
3184 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3185 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3186 "Boot/BootSourceOverrideTarget", bootSource,
3187 "Boot/BootSourceOverrideMode", bootType,
3188 "Boot/BootSourceOverrideEnabled", bootEnable,
3189 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003190 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003191 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003192 "Boot/StopBootOnFault", stopBootOnFault,
Ed Tanous22d268c2022-05-19 09:39:07 -07003193 "IdlePowerSaver/Enabled", ipsEnable,
3194 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3195 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3196 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3197 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3198 {
3199 return;
3200 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003201 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003202
Ed Tanousc1e219d2023-06-07 10:34:33 -07003203 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003204
Ed Tanousc1e219d2023-06-07 10:34:33 -07003205 if (assetTag)
3206 {
3207 setAssetTag(asyncResp, *assetTag);
3208 }
James Feistb49ac872019-05-21 15:12:01 -07003209
Ed Tanousc1e219d2023-06-07 10:34:33 -07003210 if (wdtEnable || wdtTimeOutAction)
3211 {
3212 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3213 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003214
Ed Tanousc1e219d2023-06-07 10:34:33 -07003215 if (bootSource || bootType || bootEnable)
3216 {
3217 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3218 }
3219 if (bootAutomaticRetry)
3220 {
3221 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3222 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003223
Ed Tanousc1e219d2023-06-07 10:34:33 -07003224 if (bootAutomaticRetryAttempts)
3225 {
3226 setAutomaticRetryAttempts(asyncResp,
3227 bootAutomaticRetryAttempts.value());
3228 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003229
Ed Tanousc1e219d2023-06-07 10:34:33 -07003230 if (bootTrustedModuleRequired)
3231 {
3232 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3233 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003234
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003235 if (stopBootOnFault)
3236 {
3237 setStopBootOnFault(asyncResp, *stopBootOnFault);
3238 }
3239
Ed Tanousc1e219d2023-06-07 10:34:33 -07003240 if (locationIndicatorActive)
3241 {
George Liu59a17e42022-10-08 09:27:47 +08003242 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003243 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003244
Ed Tanousc1e219d2023-06-07 10:34:33 -07003245 // TODO (Gunnar): Remove IndicatorLED after enough time has
3246 // passed
3247 if (indicatorLed)
3248 {
3249 setIndicatorLedState(asyncResp, *indicatorLed);
3250 asyncResp->res.addHeader(boost::beast::http::field::warning,
3251 "299 - \"IndicatorLED is deprecated. Use "
3252 "LocationIndicatorActive instead.\"");
3253 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003254
Ed Tanousc1e219d2023-06-07 10:34:33 -07003255 if (powerRestorePolicy)
3256 {
3257 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3258 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003259
Ed Tanousc1e219d2023-06-07 10:34:33 -07003260 if (powerMode)
3261 {
3262 setPowerMode(asyncResp, *powerMode);
3263 }
Chris Cain37bbf982021-09-20 10:53:09 -05003264
Ed Tanousc1e219d2023-06-07 10:34:33 -07003265 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3266 {
3267 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3268 ipsExitUtil, ipsExitTime);
3269 }
3270}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303271
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003272inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003273 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003274 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003275 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003276{
3277 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3278 {
3279 return;
3280 }
3281 asyncResp->res.addHeader(
3282 boost::beast::http::field::link,
3283 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3284}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003285
3286/**
3287 * @brief Translates allowed host transitions to redfish string
3288 *
3289 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3290 * @param[out] allowableValues The translated host transition(s)
3291 *
3292 * @return Emplaces correpsonding Redfish translated value(s) in
3293 * allowableValues. If translation not possible, does nothing to
3294 * allowableValues.
3295 */
3296inline void
3297 dbusToRfAllowedHostTransitions(const std::string& dbusAllowedHostTran,
3298 nlohmann::json::array_t& allowableValues)
3299{
3300 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3301 {
3302 allowableValues.emplace_back(resource::ResetType::On);
3303 allowableValues.emplace_back(resource::ResetType::ForceOn);
3304 }
3305 else if (dbusAllowedHostTran ==
3306 "xyz.openbmc_project.State.Host.Transition.Off")
3307 {
3308 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3309 }
3310 else if (dbusAllowedHostTran ==
3311 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3312 {
3313 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3314 }
3315 else if (dbusAllowedHostTran ==
3316 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3317 {
3318 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3319 }
3320 else
3321 {
3322 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3323 }
3324}
3325
3326inline void afterGetAllowedHostTransitions(
3327 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3328 const boost::system::error_code& ec,
3329 const std::vector<std::string>& allowedHostTransitions)
3330{
3331 nlohmann::json::array_t allowableValues;
3332
3333 // Supported on all systems currently
3334 allowableValues.emplace_back(resource::ResetType::ForceOff);
3335 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3336 allowableValues.emplace_back(resource::ResetType::Nmi);
3337
3338 if (ec)
3339 {
Ed Tanouse715d142024-03-07 15:47:37 -08003340 if ((ec.value() ==
3341 boost::system::linux_error::bad_request_descriptor) ||
3342 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003343 {
3344 // Property not implemented so just return defaults
3345 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3346 allowableValues.emplace_back(resource::ResetType::On);
3347 allowableValues.emplace_back(resource::ResetType::ForceOn);
3348 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3349 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3350 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3351 }
3352 else
3353 {
3354 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3355 messages::internalError(asyncResp->res);
3356 return;
3357 }
3358 }
3359 else
3360 {
3361 for (const std::string& transition : allowedHostTransitions)
3362 {
3363 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3364 dbusToRfAllowedHostTransitions(transition, allowableValues);
3365 }
3366 }
3367
3368 nlohmann::json::object_t parameter;
3369 parameter["Name"] = "ResetType";
3370 parameter["Required"] = true;
3371 parameter["DataType"] = "String";
3372 parameter["AllowableValues"] = std::move(allowableValues);
3373 nlohmann::json::array_t parameters;
3374 parameters.emplace_back(std::move(parameter));
3375 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3376}
3377
Ed Tanousc1e219d2023-06-07 10:34:33 -07003378inline void handleSystemCollectionResetActionGet(
3379 crow::App& app, const crow::Request& req,
3380 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3381 const std::string& systemName)
3382{
3383 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3384 {
3385 return;
3386 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003387 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003388 {
3389 // Option currently returns no systems. TBD
3390 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3391 systemName);
3392 return;
3393 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003394
Ed Tanousc1e219d2023-06-07 10:34:33 -07003395 if (systemName == "hypervisor")
3396 {
3397 handleHypervisorResetActionGet(asyncResp);
3398 return;
3399 }
3400
Ed Tanous253f11b2024-05-16 09:38:31 -07003401 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003402 {
3403 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3404 systemName);
3405 return;
3406 }
3407
3408 asyncResp->res.addHeader(
3409 boost::beast::http::field::link,
3410 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3411
3412 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003413 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3414 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003415 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3416 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3417 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3418
Andrew Geissler33e1f122024-02-26 21:10:16 -06003419 // Look to see if system defines AllowedHostTransitions
3420 sdbusplus::asio::getProperty<std::vector<std::string>>(
3421 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
3422 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
3423 "AllowedHostTransitions",
3424 [asyncResp](const boost::system::error_code& ec,
3425 const std::vector<std::string>& allowedHostTransitions) {
3426 afterGetAllowedHostTransitions(asyncResp, ec, allowedHostTransitions);
3427 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003428}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303429/**
3430 * SystemResetActionInfo derived class for delivering Computer Systems
3431 * ResetType AllowableValues using ResetInfo schema.
3432 */
Ed Tanous100afe52023-06-07 13:30:46 -07003433inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303434{
Ed Tanous100afe52023-06-07 13:30:46 -07003435 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3436 .privileges(redfish::privileges::headComputerSystemCollection)
3437 .methods(boost::beast::http::verb::head)(
3438 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3439
3440 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3441 .privileges(redfish::privileges::getComputerSystemCollection)
3442 .methods(boost::beast::http::verb::get)(
3443 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3444
3445 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3446 .privileges(redfish::privileges::headComputerSystem)
3447 .methods(boost::beast::http::verb::head)(
3448 std::bind_front(handleComputerSystemHead, std::ref(app)));
3449
3450 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3451 .privileges(redfish::privileges::getComputerSystem)
3452 .methods(boost::beast::http::verb::get)(
3453 std::bind_front(handleComputerSystemGet, std::ref(app)));
3454
3455 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3456 .privileges(redfish::privileges::patchComputerSystem)
3457 .methods(boost::beast::http::verb::patch)(
3458 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3459
3460 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3461 .privileges(redfish::privileges::postComputerSystem)
3462 .methods(boost::beast::http::verb::post)(std::bind_front(
3463 handleComputerSystemResetActionPost, std::ref(app)));
3464
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003465 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003466 .privileges(redfish::privileges::headActionInfo)
3467 .methods(boost::beast::http::verb::head)(std::bind_front(
3468 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003469 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003470 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003471 .methods(boost::beast::http::verb::get)(std::bind_front(
3472 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003473}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003474} // namespace redfish