blob: 8a0b1c380213dd2138129124e7c75c7293b0fef7 [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 Tanous539d8c62024-06-19 14:38:27 -070023#include "generated/enums/action_info.hpp"
Ed Tanous8d69c662023-06-21 10:29:06 -070024#include "generated/enums/computer_system.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070025#include "generated/enums/open_bmc_computer_system.hpp"
Andrew Geissler33e1f122024-02-26 21:10:16 -060026#include "generated/enums/resource.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060027#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080028#include "led.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070029#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080030#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080031#include "registries/privilege_registry.hpp"
32#include "utils/dbus_utils.hpp"
33#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050034#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080035#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070036#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080037
Andrew Geisslerfc903b32023-05-31 14:15:42 -040038#include <boost/asio/error.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070039#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080040#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060041#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070042#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070043#include <sdbusplus/asio/property.hpp>
Andrew Geisslerfc903b32023-05-31 14:15:42 -040044#include <sdbusplus/message.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020045#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050046
George Liu7a1dbc42022-12-07 16:03:22 +080047#include <array>
Andrew Geissler33e1f122024-02-26 21:10:16 -060048#include <memory>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060049#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080050#include <string_view>
Ed Tanous20fa6a22024-05-20 18:02:58 -070051#include <utility>
Ed Tanousabf2add2019-01-22 16:40:12 -080052#include <variant>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060053#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020054
Ed Tanous1abe55e2018-09-05 08:30:59 -070055namespace redfish
56{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020057
Abhishek Patel5c3e9272021-06-24 10:11:33 -050058const static std::array<std::pair<std::string_view, std::string_view>, 2>
59 protocolToDBusForSystems{
60 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
61
Alpana Kumari9d3ae102019-04-12 06:49:32 -050062/**
63 * @brief Updates the Functional State of DIMMs
64 *
Ed Tanousac106bf2023-06-07 09:24:59 -070065 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari9d3ae102019-04-12 06:49:32 -050066 * @param[in] dimmState Dimm's Functional state, true/false
67 *
68 * @return None.
69 */
zhanghch058d1b46d2021-04-01 11:18:24 +080070inline void
Ed Tanousac106bf2023-06-07 09:24:59 -070071 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070072 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050073{
Ed Tanous62598e32023-07-17 17:06:25 -070074 BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050075
Gunnar Mills4e0453b2020-07-08 14:00:30 -050076 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050077 // Update STATE only if previous State was DISABLED and current Dimm is
78 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070079 const nlohmann::json& prevMemSummary =
Ed Tanousac106bf2023-06-07 09:24:59 -070080 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"];
Alpana Kumari9d3ae102019-04-12 06:49:32 -050081 if (prevMemSummary == "Disabled")
82 {
Ed Tanouse05aec52022-01-25 10:28:56 -080083 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050084 {
Ed Tanousac106bf2023-06-07 09:24:59 -070085 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050086 "Enabled";
87 }
88 }
89}
90
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092 * @brief Update "ProcessorSummary" "Status" "State" based on
93 * CPU Functional State
94 *
Ed Tanousac106bf2023-06-07 09:24:59 -070095 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050096 * @param[in] cpuFunctionalState is CPU functional true/false
97 *
98 * @return None.
99 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700100inline void modifyCpuFunctionalState(
101 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500102{
Ed Tanous62598e32023-07-17 17:06:25 -0700103 BMCWEB_LOG_DEBUG("Cpu Functional: {}", isCpuFunctional);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500104
Ed Tanous02cad962022-06-30 16:50:15 -0700105 const nlohmann::json& prevProcState =
Ed Tanousac106bf2023-06-07 09:24:59 -0700106 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500107
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500108 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500109 // Update STATE only if previous State was Non_Functional and current CPU is
110 // Functional.
111 if (prevProcState == "Disabled")
112 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800113 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700115 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500116 "Enabled";
117 }
118 }
119}
120
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500121/*
122 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
123 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700124 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500125 * @param[in] cpuPresenceState CPU present or not
126 *
127 * @return None.
128 */
129inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700130 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500131 bool isCpuPresent)
132{
Ed Tanous62598e32023-07-17 17:06:25 -0700133 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500134
135 if (isCpuPresent)
136 {
137 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -0700138 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500139 auto* procCountPtr =
140 procCount.get_ptr<nlohmann::json::number_integer_t*>();
141 if (procCountPtr != nullptr)
142 {
143 // shouldn't be possible to be nullptr
144 *procCountPtr += 1;
145 }
146 }
147}
148
Ali Ahmed382d6472021-09-03 16:53:53 -0500149inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -0700150 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -0500151 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
152 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153{
Ed Tanous62598e32023-07-17 17:06:25 -0700154 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -0500155
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200156 // TODO: Get Model
157
158 const uint16_t* coreCount = nullptr;
159
160 const bool success = sdbusplus::unpackPropertiesNoThrow(
161 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
162
163 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500164 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700165 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200166 return;
167 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500168
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200169 if (coreCount != nullptr)
170 {
171 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700172 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200173 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500174
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200175 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500176 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200177 coreCountJson = *coreCount;
178 }
179 else
180 {
181 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500182 }
183 }
184}
185
186/*
187 * @brief Get ProcessorSummary fields
188 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700189 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500190 * @param[in] service dbus service for Cpu Information
191 * @param[in] path dbus path for Cpu
192 *
193 * @return None.
194 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700195inline void
196 getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
197 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500198{
Ed Tanousac106bf2023-06-07 09:24:59 -0700199 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
200 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500201 if (ec3)
202 {
Ed Tanous62598e32023-07-17 17:06:25 -0700203 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500204 return;
205 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700206 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500207 };
208
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500209 // Get the Presence of CPU
210 sdbusplus::asio::getProperty<bool>(
211 *crow::connections::systemBus, service, path,
212 "xyz.openbmc_project.Inventory.Item", "Present",
213 std::move(getCpuPresenceState));
214
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200215 sdbusplus::asio::getAllProperties(
216 *crow::connections::systemBus, service, path,
217 "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700218 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800219 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800220 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700221 if (ec2)
222 {
Ed Tanous62598e32023-07-17 17:06:25 -0700223 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700224 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700225 return;
226 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700227 getProcessorProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500228 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500229}
230
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500231/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500232 * @brief processMemoryProperties fields
233 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700234 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500235 * @param[in] DBUS properties for memory
236 *
237 * @return None.
238 */
239inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700240 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500241 const dbus::utility::DBusPropertiesMap& properties)
242{
Ed Tanous62598e32023-07-17 17:06:25 -0700243 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500244
245 if (properties.empty())
246 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500247 return;
248 }
249
250 const size_t* memorySizeInKB = nullptr;
251
252 const bool success = sdbusplus::unpackPropertiesNoThrow(
253 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
254 memorySizeInKB);
255
256 if (!success)
257 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700258 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500259 return;
260 }
261
262 if (memorySizeInKB != nullptr)
263 {
264 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700265 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500266 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500267 if (preValue == nullptr)
268 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700269 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500270 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500271 }
272 else
273 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700274 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500275 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
276 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500277 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500278 }
279}
280
281/*
282 * @brief Get getMemorySummary fields
283 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700284 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500285 * @param[in] service dbus service for memory Information
286 * @param[in] path dbus path for memory
287 *
288 * @return None.
289 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700290inline void
291 getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
292 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500293{
294 sdbusplus::asio::getAllProperties(
295 *crow::connections::systemBus, service, path,
296 "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700297 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500298 path](const boost::system::error_code& ec2,
299 const dbus::utility::DBusPropertiesMap& properties) {
300 if (ec2)
301 {
Ed Tanous62598e32023-07-17 17:06:25 -0700302 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -0700303 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500304 return;
305 }
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500306 processMemoryProperties(asyncResp, properties);
Patrick Williams5a39f772023-10-20 11:20:21 -0500307 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500308}
309
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500310inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
311 const boost::system::error_code& ec,
312 const dbus::utility::DBusPropertiesMap& properties)
313{
314 if (ec)
315 {
316 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
317 messages::internalError(asyncResp->res);
318 return;
319 }
320 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
321
322 const std::string* uUID = nullptr;
323
324 const bool success = sdbusplus::unpackPropertiesNoThrow(
325 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
326
327 if (!success)
328 {
329 messages::internalError(asyncResp->res);
330 return;
331 }
332
333 if (uUID != nullptr)
334 {
335 std::string valueStr = *uUID;
336 if (valueStr.size() == 32)
337 {
338 valueStr.insert(8, 1, '-');
339 valueStr.insert(13, 1, '-');
340 valueStr.insert(18, 1, '-');
341 valueStr.insert(23, 1, '-');
342 }
343 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
344 asyncResp->res.jsonValue["UUID"] = valueStr;
345 }
346}
347
348inline void
349 afterGetInventory(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
350 const boost::system::error_code& ec,
351 const dbus::utility::DBusPropertiesMap& propertiesList)
352{
353 if (ec)
354 {
355 // doesn't have to include this
356 // interface
357 return;
358 }
359 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
360
361 const std::string* partNumber = nullptr;
362 const std::string* serialNumber = nullptr;
363 const std::string* manufacturer = nullptr;
364 const std::string* model = nullptr;
365 const std::string* subModel = nullptr;
366
367 const bool success = sdbusplus::unpackPropertiesNoThrow(
368 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
369 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
370 "Model", model, "SubModel", subModel);
371
372 if (!success)
373 {
374 messages::internalError(asyncResp->res);
375 return;
376 }
377
378 if (partNumber != nullptr)
379 {
380 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
381 }
382
383 if (serialNumber != nullptr)
384 {
385 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
386 }
387
388 if (manufacturer != nullptr)
389 {
390 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
391 }
392
393 if (model != nullptr)
394 {
395 asyncResp->res.jsonValue["Model"] = *model;
396 }
397
398 if (subModel != nullptr)
399 {
400 asyncResp->res.jsonValue["SubModel"] = *subModel;
401 }
402
403 // Grab the bios version
404 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
405 "BiosVersion", false);
406}
407
408inline void
409 afterGetAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
410 const boost::system::error_code& ec,
411 const std::string& value)
412{
413 if (ec)
414 {
415 // doesn't have to include this
416 // interface
417 return;
418 }
419
420 asyncResp->res.jsonValue["AssetTag"] = value;
421}
422
423inline void afterSystemGetSubTree(
424 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500425 const boost::system::error_code& ec,
426 const dbus::utility::MapperGetSubTreeResponse& subtree)
427{
428 if (ec)
429 {
430 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
431 messages::internalError(asyncResp->res);
432 return;
433 }
434 // Iterate over all retrieved ObjectPaths.
435 for (const std::pair<
436 std::string,
437 std::vector<std::pair<std::string, std::vector<std::string>>>>&
438 object : subtree)
439 {
440 const std::string& path = object.first;
441 BMCWEB_LOG_DEBUG("Got path: {}", path);
442 const std::vector<std::pair<std::string, std::vector<std::string>>>&
443 connectionNames = object.second;
444 if (connectionNames.empty())
445 {
446 continue;
447 }
448
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500449 // This is not system, so check if it's cpu, dimm, UUID or
450 // BiosVer
451 for (const auto& connection : connectionNames)
452 {
453 for (const auto& interfaceName : connection.second)
454 {
455 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
456 {
457 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
458
459 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500460 }
461 else if (interfaceName ==
462 "xyz.openbmc_project.Inventory.Item.Cpu")
463 {
464 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
465
466 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500467 }
468 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
469 {
470 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
471
472 sdbusplus::asio::getAllProperties(
473 *crow::connections::systemBus, connection.first, path,
474 "xyz.openbmc_project.Common.UUID",
475 [asyncResp](const boost::system::error_code& ec3,
476 const dbus::utility::DBusPropertiesMap&
477 properties) {
478 afterGetUUID(asyncResp, ec3, properties);
479 });
480 }
481 else if (interfaceName ==
482 "xyz.openbmc_project.Inventory.Item.System")
483 {
484 sdbusplus::asio::getAllProperties(
485 *crow::connections::systemBus, connection.first, path,
486 "xyz.openbmc_project.Inventory.Decorator.Asset",
487 [asyncResp](const boost::system::error_code& ec3,
488 const dbus::utility::DBusPropertiesMap&
489 properties) {
490 afterGetInventory(asyncResp, ec3, properties);
491 });
492
493 sdbusplus::asio::getProperty<std::string>(
494 *crow::connections::systemBus, connection.first, path,
495 "xyz.openbmc_project.Inventory.Decorator."
496 "AssetTag",
497 "AssetTag",
498 std::bind_front(afterGetAssetTag, asyncResp));
499 }
500 }
501 }
502 }
503}
504
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500505/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700506 * @brief Retrieves computer system properties over dbus
507 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700508 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700509 *
510 * @return None.
511 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700512inline void
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500513 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700514{
Ed Tanous62598e32023-07-17 17:06:25 -0700515 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800516 constexpr std::array<std::string_view, 5> interfaces = {
517 "xyz.openbmc_project.Inventory.Decorator.Asset",
518 "xyz.openbmc_project.Inventory.Item.Cpu",
519 "xyz.openbmc_project.Inventory.Item.Dimm",
520 "xyz.openbmc_project.Inventory.Item.System",
521 "xyz.openbmc_project.Common.UUID",
522 };
523 dbus::utility::getSubTree(
524 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500525 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700526}
527
528/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700529 * @brief Retrieves host state properties over dbus
530 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700531 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Ed Tanous6c34de42018-08-29 13:37:36 -0700532 *
533 * @return None.
534 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700535inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700536{
Ed Tanous62598e32023-07-17 17:06:25 -0700537 BMCWEB_LOG_DEBUG("Get host information.");
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700538 sdbusplus::asio::getProperty<std::string>(
539 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
540 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
541 "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700542 [asyncResp](const boost::system::error_code& ec,
543 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700544 if (ec)
545 {
546 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700547 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700548 // Service not available, no error, just don't return
549 // host state info
Ed Tanous62598e32023-07-17 17:06:25 -0700550 BMCWEB_LOG_DEBUG("Service not available {}", ec);
Ed Tanous6c34de42018-08-29 13:37:36 -0700551 return;
552 }
Ed Tanous62598e32023-07-17 17:06:25 -0700553 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700554 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700555 return;
556 }
Ed Tanous66173382018-08-15 18:20:59 -0700557
Ed Tanous62598e32023-07-17 17:06:25 -0700558 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 // Verify Host State
560 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
561 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700562 asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On;
563 asyncResp->res.jsonValue["Status"]["State"] =
564 resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -0700565 }
566 else if (hostState ==
567 "xyz.openbmc_project.State.Host.HostState.Quiesced")
568 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700569 asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On;
570 asyncResp->res.jsonValue["Status"]["State"] =
571 resource::State::Quiesced;
Ed Tanous002d39b2022-05-31 08:59:27 -0700572 }
573 else if (hostState ==
574 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
575 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700576 asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On;
577 asyncResp->res.jsonValue["Status"]["State"] =
578 resource::State::InTest;
Ed Tanous002d39b2022-05-31 08:59:27 -0700579 }
580 else if (
581 hostState ==
582 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
583 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700584 asyncResp->res.jsonValue["PowerState"] =
585 resource::PowerState::PoweringOn;
586 asyncResp->res.jsonValue["Status"]["State"] =
587 resource::State::Starting;
Ed Tanous002d39b2022-05-31 08:59:27 -0700588 }
589 else if (hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
591 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700592 asyncResp->res.jsonValue["PowerState"] =
593 resource::PowerState::PoweringOff;
594 asyncResp->res.jsonValue["Status"]["State"] =
595 resource::State::Disabled;
Ed Tanous002d39b2022-05-31 08:59:27 -0700596 }
597 else
598 {
Ed Tanous539d8c62024-06-19 14:38:27 -0700599 asyncResp->res.jsonValue["PowerState"] = resource::PowerState::Off;
600 asyncResp->res.jsonValue["Status"]["State"] =
601 resource::State::Disabled;
Ed Tanous002d39b2022-05-31 08:59:27 -0700602 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500603 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700604}
605
606/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500607 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530608 *
609 * @param[in] dbusSource The boot source in DBUS speak.
610 *
611 * @return Returns as a string, the boot source in Redfish terms. If translation
612 * cannot be done, returns an empty string.
613 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000614inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615{
616 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
617 {
618 return "None";
619 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700620 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530621 {
622 return "Hdd";
623 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700624 if (dbusSource ==
625 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530626 {
627 return "Cd";
628 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700629 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 {
631 return "Pxe";
632 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700633 if (dbusSource ==
634 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700635 {
636 return "Usb";
637 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700638 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530639}
640
641/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300642 * @brief Translates boot type DBUS property value to redfish.
643 *
644 * @param[in] dbusType The boot type in DBUS speak.
645 *
646 * @return Returns as a string, the boot type in Redfish terms. If translation
647 * cannot be done, returns an empty string.
648 */
649inline std::string dbusToRfBootType(const std::string& dbusType)
650{
651 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
652 {
653 return "Legacy";
654 }
655 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
656 {
657 return "UEFI";
658 }
659 return "";
660}
661
662/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500663 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530664 *
665 * @param[in] dbusMode The boot mode in DBUS speak.
666 *
667 * @return Returns as a string, the boot mode in Redfish terms. If translation
668 * cannot be done, returns an empty string.
669 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000670inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530671{
672 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
673 {
674 return "None";
675 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700676 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530677 {
678 return "Diags";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "BiosSetup";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685}
686
687/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600688 * @brief Translates boot progress DBUS property value to redfish.
689 *
690 * @param[in] dbusBootProgress The boot progress in DBUS speak.
691 *
692 * @return Returns as a string, the boot progress in Redfish terms. If
693 * translation cannot be done, returns "None".
694 */
695inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
696{
697 // Now convert the D-Bus BootProgress to the appropriate Redfish
698 // enum
699 std::string rfBpLastState = "None";
700 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
701 "ProgressStages.Unspecified")
702 {
703 rfBpLastState = "None";
704 }
705 else if (dbusBootProgress ==
706 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
707 "PrimaryProcInit")
708 {
709 rfBpLastState = "PrimaryProcessorInitializationStarted";
710 }
711 else if (dbusBootProgress ==
712 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
713 "BusInit")
714 {
715 rfBpLastState = "BusInitializationStarted";
716 }
717 else if (dbusBootProgress ==
718 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
719 "MemoryInit")
720 {
721 rfBpLastState = "MemoryInitializationStarted";
722 }
723 else if (dbusBootProgress ==
724 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
725 "SecondaryProcInit")
726 {
727 rfBpLastState = "SecondaryProcessorInitializationStarted";
728 }
729 else if (dbusBootProgress ==
730 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
731 "PCIInit")
732 {
733 rfBpLastState = "PCIResourceConfigStarted";
734 }
735 else if (dbusBootProgress ==
736 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
737 "SystemSetup")
738 {
739 rfBpLastState = "SetupEntered";
740 }
741 else if (dbusBootProgress ==
742 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
743 "SystemInitComplete")
744 {
745 rfBpLastState = "SystemHardwareInitializationComplete";
746 }
747 else if (dbusBootProgress ==
748 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
749 "OSStart")
750 {
751 rfBpLastState = "OSBootStarted";
752 }
753 else if (dbusBootProgress ==
754 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
755 "OSRunning")
756 {
757 rfBpLastState = "OSRunning";
758 }
759 else
760 {
Ed Tanous62598e32023-07-17 17:06:25 -0700761 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600762 // Just return the default
763 }
764 return rfBpLastState;
765}
766
767/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500768 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530769 *
770 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700771 * @param[out] bootSource The DBus source
772 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700774 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530775 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700776inline int
777 assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
778 const std::string& rfSource, std::string& bootSource,
779 std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300781 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
782 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 if (rfSource == "None")
785 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700786 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700788 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
791 }
792 else if (rfSource == "Hdd")
793 {
794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
795 }
796 else if (rfSource == "Diags")
797 {
798 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
799 }
800 else if (rfSource == "Cd")
801 {
802 bootSource =
803 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
804 }
805 else if (rfSource == "BiosSetup")
806 {
807 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530808 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700809 else if (rfSource == "Usb")
810 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700811 bootSource =
812 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530814 else
815 {
Ed Tanous62598e32023-07-17 17:06:25 -0700816 BMCWEB_LOG_DEBUG(
817 "Invalid property value for BootSourceOverrideTarget: {}",
818 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700819 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700820 "BootSourceTargetOverride");
821 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530822 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530824}
Ali Ahmed19817712021-06-29 17:01:52 -0500825
Andrew Geissler978b8802020-11-19 13:36:40 -0600826/**
827 * @brief Retrieves boot progress of the system
828 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700829 * @param[in] asyncResp Shared pointer for generating response message.
Andrew Geissler978b8802020-11-19 13:36:40 -0600830 *
831 * @return None.
832 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700833inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600834{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700835 sdbusplus::asio::getProperty<std::string>(
836 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
837 "/xyz/openbmc_project/state/host0",
838 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700839 [asyncResp](const boost::system::error_code& ec,
840 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700841 if (ec)
842 {
843 // BootProgress is an optional object so just do nothing if
844 // not found
845 return;
846 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600847
Ed Tanous62598e32023-07-17 17:06:25 -0700848 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600849
Ed Tanousac106bf2023-06-07 09:24:59 -0700850 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700851 dbusToRfBootProgress(bootProgressStr);
Patrick Williams5a39f772023-10-20 11:20:21 -0500852 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600853}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530854
855/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000856 * @brief Retrieves boot progress Last Update of the system
857 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700858 * @param[in] asyncResp Shared pointer for generating response message.
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000859 *
860 * @return None.
861 */
862inline void getBootProgressLastStateTime(
Ed Tanousac106bf2023-06-07 09:24:59 -0700863 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000864{
865 sdbusplus::asio::getProperty<uint64_t>(
866 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
867 "/xyz/openbmc_project/state/host0",
868 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700869 [asyncResp](const boost::system::error_code& ec,
870 const uint64_t lastStateTime) {
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000871 if (ec)
872 {
Ed Tanous62598e32023-07-17 17:06:25 -0700873 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000874 return;
875 }
876
877 // BootProgressLastUpdate is the last time the BootProgress property
878 // was updated. The time is the Epoch time, number of microseconds
879 // since 1 Jan 1970 00::00::00 UTC."
880 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
881 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
882
883 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -0700884 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000885 redfish::time_utils::getDateTimeUintUs(lastStateTime);
Patrick Williams5a39f772023-10-20 11:20:21 -0500886 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000887}
888
889/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300890 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300891 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700892 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300893 *
894 * @return None.
895 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300896
Ed Tanousac106bf2023-06-07 09:24:59 -0700897inline void
898 getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300899{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700900 sdbusplus::asio::getProperty<std::string>(
901 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
902 "/xyz/openbmc_project/control/host0/boot",
903 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700904 [asyncResp](const boost::system::error_code& ec,
905 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700906 if (ec)
907 {
908 // not an error, don't have to have the interface
909 return;
910 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300911
Ed Tanous62598e32023-07-17 17:06:25 -0700912 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300913
Ed Tanousac106bf2023-06-07 09:24:59 -0700914 asyncResp->res
915 .jsonValue["Boot"]
916 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700917 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918
Ed Tanous002d39b2022-05-31 08:59:27 -0700919 auto rfType = dbusToRfBootType(bootType);
920 if (rfType.empty())
921 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700922 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700923 return;
924 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300925
Ed Tanousac106bf2023-06-07 09:24:59 -0700926 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Patrick Williams5a39f772023-10-20 11:20:21 -0500927 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300928}
929
930/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300931 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530932 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700933 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530934 *
935 * @return None.
936 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300937
Ed Tanousac106bf2023-06-07 09:24:59 -0700938inline void
939 getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700941 sdbusplus::asio::getProperty<std::string>(
942 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
943 "/xyz/openbmc_project/control/host0/boot",
944 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700945 [asyncResp](const boost::system::error_code& ec,
946 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700947 if (ec)
948 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -0500949 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -0700950 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -0700951 return;
952 }
953
Ed Tanous62598e32023-07-17 17:06:25 -0700954 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
Ed Tanous002d39b2022-05-31 08:59:27 -0700955
Ed Tanous20fa6a22024-05-20 18:02:58 -0700956 nlohmann::json::array_t allowed;
957 allowed.emplace_back("None");
958 allowed.emplace_back("Pxe");
959 allowed.emplace_back("Hdd");
960 allowed.emplace_back("Cd");
961 allowed.emplace_back("Diags");
962 allowed.emplace_back("BiosSetup");
963 allowed.emplace_back("Usb");
964
Ed Tanousac106bf2023-06-07 09:24:59 -0700965 asyncResp->res
Ed Tanous002d39b2022-05-31 08:59:27 -0700966 .jsonValue["Boot"]
Ed Tanous20fa6a22024-05-20 18:02:58 -0700967 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
968 std::move(allowed);
Ed Tanous002d39b2022-05-31 08:59:27 -0700969 if (bootModeStr !=
970 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
971 {
972 auto rfMode = dbusToRfBootMode(bootModeStr);
973 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700975 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700976 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530977 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700978 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500979 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530980}
981
982/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300983 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530984 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700985 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986 *
987 * @return None.
988 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300989
990inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700991 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530992{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700993 sdbusplus::asio::getProperty<std::string>(
994 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
995 "/xyz/openbmc_project/control/host0/boot",
996 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanousac106bf2023-06-07 09:24:59 -0700997 [asyncResp](const boost::system::error_code& ec,
998 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700999 if (ec)
1000 {
Nan Zhou5ef735c2022-06-22 05:24:21 +00001001 if (ec.value() == boost::asio::error::host_unreachable)
1002 {
1003 return;
1004 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001005 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001006 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001007 return;
1008 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301009
Ed Tanous62598e32023-07-17 17:06:25 -07001010 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301011
Ed Tanous002d39b2022-05-31 08:59:27 -07001012 auto rfSource = dbusToRfBootSource(bootSourceStr);
1013 if (!rfSource.empty())
1014 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001015 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1016 rfSource;
Ed Tanous002d39b2022-05-31 08:59:27 -07001017 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001018
Ed Tanous002d39b2022-05-31 08:59:27 -07001019 // Get BootMode as BootSourceOverrideTarget is constructed
1020 // from both BootSource and BootMode
Ed Tanousac106bf2023-06-07 09:24:59 -07001021 getBootOverrideMode(asyncResp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001022 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301023}
1024
1025/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001026 * @brief This functions abstracts all the logic behind getting a
1027 * "BootSourceOverrideEnabled" property from an overall boot override enable
1028 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001030 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301031 *
1032 * @return None.
1033 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034
Ed Tanousac106bf2023-06-07 09:24:59 -07001035inline void processBootOverrideEnable(
1036 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1037 const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001038{
1039 if (!bootOverrideEnableSetting)
1040 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001041 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1042 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 return;
1044 }
1045
1046 // If boot source override is enabled, we need to check 'one_time'
1047 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001048 sdbusplus::asio::getProperty<bool>(
1049 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1050 "/xyz/openbmc_project/control/host0/boot/one_time",
1051 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001052 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001053 if (ec)
1054 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001055 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001056 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001057 return;
1058 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301059
Ed Tanous002d39b2022-05-31 08:59:27 -07001060 if (oneTimeSetting)
1061 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001062 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1063 "Once";
Ed Tanous002d39b2022-05-31 08:59:27 -07001064 }
1065 else
1066 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001067 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001068 "Continuous";
1069 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001070 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301071}
1072
1073/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074 * @brief Retrieves boot override enable over DBUS
1075 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001076 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001077 *
1078 * @return None.
1079 */
1080
1081inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001082 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001083{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001084 sdbusplus::asio::getProperty<bool>(
1085 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1086 "/xyz/openbmc_project/control/host0/boot",
1087 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001088 [asyncResp](const boost::system::error_code& ec,
1089 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001090 if (ec)
1091 {
Nan Zhou5ef735c2022-06-22 05:24:21 +00001092 if (ec.value() == boost::asio::error::host_unreachable)
1093 {
1094 return;
1095 }
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001096 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001097 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001098 return;
1099 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001100
Ed Tanousac106bf2023-06-07 09:24:59 -07001101 processBootOverrideEnable(asyncResp, bootOverrideEnable);
Patrick Williams5a39f772023-10-20 11:20:21 -05001102 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001103}
1104
1105/**
1106 * @brief Retrieves boot source override properties
1107 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001108 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001109 *
1110 * @return None.
1111 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001112inline void
1113 getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001114{
Ed Tanous62598e32023-07-17 17:06:25 -07001115 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001116
Ed Tanousac106bf2023-06-07 09:24:59 -07001117 getBootOverrideSource(asyncResp);
1118 getBootOverrideType(asyncResp);
1119 getBootOverrideEnable(asyncResp);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001120}
1121
1122/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001123 * @brief Retrieves the Last Reset Time
1124 *
1125 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1126 * and power off. Even though this is the "system" Redfish object look at the
1127 * chassis D-Bus interface for the LastStateChangeTime since this has the
1128 * last power operation time.
1129 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001130 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001131 *
1132 * @return None.
1133 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001134inline void
1135 getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001136{
Ed Tanous62598e32023-07-17 17:06:25 -07001137 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001138
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001139 sdbusplus::asio::getProperty<uint64_t>(
1140 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1141 "/xyz/openbmc_project/state/chassis0",
1142 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001143 [asyncResp](const boost::system::error_code& ec,
1144 uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 if (ec)
1146 {
Ed Tanous62598e32023-07-17 17:06:25 -07001147 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001148 return;
1149 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001150
Ed Tanous002d39b2022-05-31 08:59:27 -07001151 // LastStateChangeTime is epoch time, in milliseconds
1152 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1153 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001154
Ed Tanous002d39b2022-05-31 08:59:27 -07001155 // Convert to ISO 8601 standard
Ed Tanousac106bf2023-06-07 09:24:59 -07001156 asyncResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001157 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Patrick Williams5a39f772023-10-20 11:20:21 -05001158 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001159}
1160
1161/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001162 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1163 *
1164 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1165 * corresponding property "AttemptsLeft" that keeps track of the amount of
1166 * automatic retry attempts left are hosted in phosphor-state-manager through
1167 * dbus.
1168 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001169 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001170 *
1171 * @return None.
1172 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001173inline void getAutomaticRebootAttempts(
1174 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001175{
Ed Tanous62598e32023-07-17 17:06:25 -07001176 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001177
1178 sdbusplus::asio::getAllProperties(
1179 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1180 "/xyz/openbmc_project/state/host0",
1181 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001182 [asyncResp{asyncResp}](
1183 const boost::system::error_code& ec,
1184 const dbus::utility::DBusPropertiesMap& propertiesList) {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001185 if (ec)
1186 {
1187 if (ec.value() != EBADR)
1188 {
Ed Tanous62598e32023-07-17 17:06:25 -07001189 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001190 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001191 }
1192 return;
1193 }
1194
1195 const uint32_t* attemptsLeft = nullptr;
1196 const uint32_t* retryAttempts = nullptr;
1197
1198 const bool success = sdbusplus::unpackPropertiesNoThrow(
1199 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1200 attemptsLeft, "RetryAttempts", retryAttempts);
1201
1202 if (!success)
1203 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001204 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001205 return;
1206 }
1207
1208 if (attemptsLeft != nullptr)
1209 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001210 asyncResp->res
1211 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001212 *attemptsLeft;
1213 }
1214
1215 if (retryAttempts != nullptr)
1216 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001217 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
Corey Hardesty797d5da2022-04-26 17:54:52 +08001218 *retryAttempts;
1219 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001220 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001221}
1222
1223/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001224 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1225 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001226 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001227 *
1228 * @return None.
1229 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001230inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001231 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001232{
Ed Tanous62598e32023-07-17 17:06:25 -07001233 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001234
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001235 sdbusplus::asio::getProperty<bool>(
1236 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1237 "/xyz/openbmc_project/control/host0/auto_reboot",
1238 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanousac106bf2023-06-07 09:24:59 -07001239 [asyncResp](const boost::system::error_code& ec,
1240 bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001241 if (ec)
1242 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001243 if (ec.value() != EBADR)
1244 {
Ed Tanous62598e32023-07-17 17:06:25 -07001245 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001246 messages::internalError(asyncResp->res);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001247 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001248 return;
1249 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001250
Ed Tanous62598e32023-07-17 17:06:25 -07001251 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
Ed Tanous002d39b2022-05-31 08:59:27 -07001252 if (autoRebootEnabled)
1253 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001254 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001255 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001256 }
1257 else
1258 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001259 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1260 "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -07001261 }
Ed Tanousac106bf2023-06-07 09:24:59 -07001262 getAutomaticRebootAttempts(asyncResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001263
Ed Tanous002d39b2022-05-31 08:59:27 -07001264 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1265 // and RetryAttempts. OpenBMC only supports Disabled and
1266 // RetryAttempts.
Ed Tanous20fa6a22024-05-20 18:02:58 -07001267 nlohmann::json::array_t allowed;
1268 allowed.emplace_back("Disabled");
1269 allowed.emplace_back("RetryAttempts");
Ed Tanousac106bf2023-06-07 09:24:59 -07001270 asyncResp->res
1271 .jsonValue["Boot"]["AutomaticRetryConfig@Redfish.AllowableValues"] =
Ed Tanous20fa6a22024-05-20 18:02:58 -07001272 std::move(allowed);
Patrick Williams5a39f772023-10-20 11:20:21 -05001273 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001274}
1275
1276/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001277 * @brief Sets RetryAttempts
1278 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001279 * @param[in] asyncResp Shared pointer for generating response message.
Corey Hardesty797d5da2022-04-26 17:54:52 +08001280 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1281 *
1282 *@return None.
1283 */
1284
Ed Tanousac106bf2023-06-07 09:24:59 -07001285inline void setAutomaticRetryAttempts(
1286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1287 const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001288{
Ed Tanous62598e32023-07-17 17:06:25 -07001289 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001290 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301291 asyncResp, "Boot/AutomaticRetryAttempts",
1292 "xyz.openbmc_project.State.Host",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001293 sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001294 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
Ginu Georgee93abac2024-06-14 17:35:27 +05301295 retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001296}
1297
Ed Tanous8d69c662023-06-21 10:29:06 -07001298inline computer_system::PowerRestorePolicyTypes
1299 redfishPowerRestorePolicyFromDbus(std::string_view value)
1300{
1301 if (value ==
1302 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1303 {
1304 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1305 }
1306 if (value ==
1307 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1308 {
1309 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1310 }
1311 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001312 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001313 {
1314 return computer_system::PowerRestorePolicyTypes::LastState;
1315 }
1316 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1317 {
1318 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1319 }
1320 return computer_system::PowerRestorePolicyTypes::Invalid;
1321}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001322/**
George Liuc6a620f2020-04-10 17:18:11 +08001323 * @brief Retrieves power restore policy over DBUS.
1324 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001325 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001326 *
1327 * @return None.
1328 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001329inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001330 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuc6a620f2020-04-10 17:18:11 +08001331{
Ed Tanous62598e32023-07-17 17:06:25 -07001332 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001333
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001334 sdbusplus::asio::getProperty<std::string>(
1335 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1336 "/xyz/openbmc_project/control/host0/power_restore_policy",
1337 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001338 [asyncResp](const boost::system::error_code& ec,
1339 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001340 if (ec)
1341 {
Ed Tanous62598e32023-07-17 17:06:25 -07001342 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001343 return;
1344 }
Ed Tanous8d69c662023-06-21 10:29:06 -07001345 computer_system::PowerRestorePolicyTypes restore =
1346 redfishPowerRestorePolicyFromDbus(policy);
1347 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -07001348 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001349 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001350 return;
1351 }
George Liuc6a620f2020-04-10 17:18:11 +08001352
Ed Tanous8d69c662023-06-21 10:29:06 -07001353 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
Patrick Williams5a39f772023-10-20 11:20:21 -05001354 });
George Liuc6a620f2020-04-10 17:18:11 +08001355}
1356
1357/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001358 * @brief Stop Boot On Fault over DBUS.
1359 *
1360 * @param[in] asyncResp Shared pointer for generating response message.
1361 *
1362 * @return None.
1363 */
1364inline void
1365 getStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1366{
Ed Tanous62598e32023-07-17 17:06:25 -07001367 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001368
1369 sdbusplus::asio::getProperty<bool>(
1370 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1371 "/xyz/openbmc_project/logging/settings",
1372 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1373 [asyncResp](const boost::system::error_code& ec, bool value) {
1374 if (ec)
1375 {
1376 if (ec.value() != EBADR)
1377 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001378 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001379 messages::internalError(asyncResp->res);
1380 }
1381 return;
1382 }
1383
1384 if (value)
1385 {
Ed Tanous539d8c62024-06-19 14:38:27 -07001386 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1387 computer_system::StopBootOnFault::AnyFault;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001388 }
1389 else
1390 {
Ed Tanous539d8c62024-06-19 14:38:27 -07001391 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1392 computer_system::StopBootOnFault::Never;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001393 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001394 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001395}
1396
1397/**
Ali Ahmed19817712021-06-29 17:01:52 -05001398 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1399 * TPM is required for booting the host.
1400 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001401 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed19817712021-06-29 17:01:52 -05001402 *
1403 * @return None.
1404 */
1405inline void getTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001406 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ali Ahmed19817712021-06-29 17:01:52 -05001407{
Ed Tanous62598e32023-07-17 17:06:25 -07001408 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001409 constexpr std::array<std::string_view, 1> interfaces = {
1410 "xyz.openbmc_project.Control.TPM.Policy"};
1411 dbus::utility::getSubTree(
1412 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001413 [asyncResp](const boost::system::error_code& ec,
1414 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001415 if (ec)
1416 {
Ed Tanous62598e32023-07-17 17:06:25 -07001417 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}",
1418 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001419 // This is an optional D-Bus object so just return if
1420 // error occurs
1421 return;
1422 }
1423 if (subtree.empty())
1424 {
1425 // As noted above, this is an optional interface so just return
1426 // if there is no instance found
1427 return;
1428 }
1429
1430 /* When there is more than one TPMEnable object... */
1431 if (subtree.size() > 1)
1432 {
Ed Tanous62598e32023-07-17 17:06:25 -07001433 BMCWEB_LOG_DEBUG(
1434 "DBUS response has more than 1 TPM Enable object:{}",
1435 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001436 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001437 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001438 return;
1439 }
1440
1441 // Make sure the Dbus response map has a service and objectPath
1442 // field
1443 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1444 {
Ed Tanous62598e32023-07-17 17:06:25 -07001445 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001446 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001447 return;
1448 }
1449
1450 const std::string& path = subtree[0].first;
1451 const std::string& serv = subtree[0].second.begin()->first;
1452
1453 // Valid TPM Enable object found, now reading the current value
1454 sdbusplus::asio::getProperty<bool>(
1455 *crow::connections::systemBus, serv, path,
1456 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanousac106bf2023-06-07 09:24:59 -07001457 [asyncResp](const boost::system::error_code& ec2,
1458 bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001459 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001460 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001461 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001462 ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07001463 messages::internalError(asyncResp->res);
Ali Ahmed19817712021-06-29 17:01:52 -05001464 return;
1465 }
1466
Ed Tanous002d39b2022-05-31 08:59:27 -07001467 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001468 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001469 asyncResp->res
1470 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001471 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001472 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001473 else
1474 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001475 asyncResp->res
1476 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
Ed Tanous002d39b2022-05-31 08:59:27 -07001477 "Disabled";
1478 }
George Liue99073f2022-12-09 11:06:16 +08001479 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001480 });
Ali Ahmed19817712021-06-29 17:01:52 -05001481}
1482
1483/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001484 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1485 * TPM is required for booting the host.
1486 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001487 * @param[in] asyncResp Shared pointer for generating response message.
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001488 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1489 *
1490 * @return None.
1491 */
1492inline void setTrustedModuleRequiredToBoot(
Ed Tanousac106bf2023-06-07 09:24:59 -07001493 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001494{
Ed Tanous62598e32023-07-17 17:06:25 -07001495 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001496 constexpr std::array<std::string_view, 1> interfaces = {
1497 "xyz.openbmc_project.Control.TPM.Policy"};
1498 dbus::utility::getSubTree(
1499 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001500 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001501 tpmRequired](const boost::system::error_code& ec,
1502 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001503 if (ec)
1504 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05001505 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}",
Ed Tanous62598e32023-07-17 17:06:25 -07001506 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001507 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001508 return;
1509 }
1510 if (subtree.empty())
1511 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001512 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07001513 "TrustedModuleRequiredToBoot");
1514 return;
1515 }
1516
1517 /* When there is more than one TPMEnable object... */
1518 if (subtree.size() > 1)
1519 {
Ed Tanous62598e32023-07-17 17:06:25 -07001520 BMCWEB_LOG_DEBUG(
1521 "DBUS response has more than 1 TPM Enable object:{}",
1522 subtree.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07001523 // Throw an internal Error and return
Ed Tanousac106bf2023-06-07 09:24:59 -07001524 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001525 return;
1526 }
1527
1528 // Make sure the Dbus response map has a service and objectPath
1529 // field
1530 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1531 {
Ed Tanous62598e32023-07-17 17:06:25 -07001532 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001533 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001534 return;
1535 }
1536
1537 const std::string& path = subtree[0].first;
1538 const std::string& serv = subtree[0].second.begin()->first;
1539
1540 if (serv.empty())
1541 {
Ed Tanous62598e32023-07-17 17:06:25 -07001542 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001543 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001544 return;
1545 }
1546
1547 // Valid TPM Enable object found, now setting the value
Ginu Georgee93abac2024-06-14 17:35:27 +05301548 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
1549 path, "xyz.openbmc_project.Control.TPM.Policy",
1550 "TPMEnable", tpmRequired);
Patrick Williams5a39f772023-10-20 11:20:21 -05001551 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001552}
1553
1554/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301555 * @brief Sets boot properties into DBUS object(s).
1556 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001557 * @param[in] asyncResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001558 * @param[in] bootType The boot type to set.
1559 * @return Integer error code.
1560 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001561inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001562 const std::optional<std::string>& bootType)
1563{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001564 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001565
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001566 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001567 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001568 return;
1569 }
1570
1571 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001572 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001573 // Figure out which DBUS interface and property to use
1574 if (*bootType == "Legacy")
1575 {
1576 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1577 }
1578 else if (*bootType == "UEFI")
1579 {
1580 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1581 }
1582 else
1583 {
Ed Tanous62598e32023-07-17 17:06:25 -07001584 BMCWEB_LOG_DEBUG("Invalid property value for "
1585 "BootSourceOverrideMode: {}",
1586 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001587 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001588 "BootSourceOverrideMode");
1589 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001590 }
1591
1592 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001593 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001594
Ginu Georgee93abac2024-06-14 17:35:27 +05301595 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
1596 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001597 sdbusplus::message::object_path(
1598 "/xyz/openbmc_project/control/host0/boot"),
1599 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301600 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001601}
1602
1603/**
1604 * @brief Sets boot properties into DBUS object(s).
1605 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001606 * @param[in] asyncResp Shared pointer for generating response
1607 * message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001608 * @param[in] bootType The boot type to set.
1609 * @return Integer error code.
1610 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001611inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001612 const std::optional<std::string>& bootEnable)
1613{
1614 if (!bootEnable)
1615 {
1616 return;
1617 }
1618 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001619 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001620
1621 bool bootOverrideEnable = false;
1622 bool bootOverridePersistent = false;
1623 // Figure out which DBUS interface and property to use
1624 if (*bootEnable == "Disabled")
1625 {
1626 bootOverrideEnable = false;
1627 }
1628 else if (*bootEnable == "Once")
1629 {
1630 bootOverrideEnable = true;
1631 bootOverridePersistent = false;
1632 }
1633 else if (*bootEnable == "Continuous")
1634 {
1635 bootOverrideEnable = true;
1636 bootOverridePersistent = true;
1637 }
1638 else
1639 {
Ed Tanous62598e32023-07-17 17:06:25 -07001640 BMCWEB_LOG_DEBUG(
1641 "Invalid property value for BootSourceOverrideEnabled: {}",
1642 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001643 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001644 "BootSourceOverrideEnabled");
1645 return;
1646 }
1647
1648 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001649 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001650
Ginu Georgee93abac2024-06-14 17:35:27 +05301651 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1652 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001653 sdbusplus::message::object_path(
1654 "/xyz/openbmc_project/control/host0/boot"),
1655 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301656 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001657
1658 if (!bootOverrideEnable)
1659 {
1660 return;
1661 }
1662
1663 // In case boot override is enabled we need to set correct value for the
1664 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001665 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1666 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001667
Ginu Georgee93abac2024-06-14 17:35:27 +05301668 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
1669 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001670 sdbusplus::message::object_path(
1671 "/xyz/openbmc_project/control/host0/boot/one_time"),
1672 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301673 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001674}
1675
1676/**
1677 * @brief Sets boot properties into DBUS object(s).
1678 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001679 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301680 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301681 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001682 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301683 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001684inline void
1685 setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1686 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301687{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001688 std::string bootSourceStr;
1689 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001690
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001691 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301692 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001693 return;
1694 }
1695
1696 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001697 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001698 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001699 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1700 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001701 {
Ed Tanous62598e32023-07-17 17:06:25 -07001702 BMCWEB_LOG_DEBUG(
1703 "Invalid property value for BootSourceOverrideTarget: {}",
1704 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001705 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001706 "BootSourceTargetOverride");
1707 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001708 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301709
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001710 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001711 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1712 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001713
Ginu Georgee93abac2024-06-14 17:35:27 +05301714 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1715 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001716 sdbusplus::message::object_path(
1717 "/xyz/openbmc_project/control/host0/boot"),
1718 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301719 bootSourceStr);
1720 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
1721 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001722 sdbusplus::message::object_path(
1723 "/xyz/openbmc_project/control/host0/boot"),
1724 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301725 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001726}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001727
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001728/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001729 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301730 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001731 * @param[in] asyncResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001733 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301734 * @param[in] bootEnable The boot override enable from incoming RF request.
1735 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001736 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301737 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001738
Ed Tanousac106bf2023-06-07 09:24:59 -07001739inline void
1740 setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1741 const std::optional<std::string>& bootSource,
1742 const std::optional<std::string>& bootType,
1743 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301744{
Ed Tanous62598e32023-07-17 17:06:25 -07001745 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301746
Ed Tanousac106bf2023-06-07 09:24:59 -07001747 setBootModeOrSource(asyncResp, bootSource);
1748 setBootType(asyncResp, bootType);
1749 setBootEnable(asyncResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301750}
1751
George Liuc6a620f2020-04-10 17:18:11 +08001752/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001753 * @brief Sets AssetTag
1754 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001755 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001756 * @param[in] assetTag "AssetTag" from request.
1757 *
1758 * @return None.
1759 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001760inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001761 const std::string& assetTag)
1762{
George Liue99073f2022-12-09 11:06:16 +08001763 constexpr std::array<std::string_view, 1> interfaces = {
1764 "xyz.openbmc_project.Inventory.Item.System"};
1765 dbus::utility::getSubTree(
1766 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001767 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001768 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001769 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001770 if (ec)
1771 {
Ed Tanous62598e32023-07-17 17:06:25 -07001772 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07001773 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001774 return;
1775 }
1776 if (subtree.empty())
1777 {
Ed Tanous62598e32023-07-17 17:06:25 -07001778 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001779 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001780 return;
1781 }
1782 // Assume only 1 system D-Bus object
1783 // Throw an error if there is more than 1
1784 if (subtree.size() > 1)
1785 {
Ed Tanous62598e32023-07-17 17:06:25 -07001786 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001787 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001788 return;
1789 }
1790 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1791 {
Ed Tanous62598e32023-07-17 17:06:25 -07001792 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001793 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001794 return;
1795 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001796
Ed Tanous002d39b2022-05-31 08:59:27 -07001797 const std::string& path = subtree[0].first;
1798 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001799
Ed Tanous002d39b2022-05-31 08:59:27 -07001800 if (service.empty())
1801 {
Ed Tanous62598e32023-07-17 17:06:25 -07001802 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07001803 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07001804 return;
1805 }
1806
Ginu Georgee93abac2024-06-14 17:35:27 +05301807 setDbusProperty(asyncResp, "AssetTag", service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001808 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
Ginu Georgee93abac2024-06-14 17:35:27 +05301809 "AssetTag", assetTag);
Patrick Williams5a39f772023-10-20 11:20:21 -05001810 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001811}
1812
1813/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001814 * @brief Validate the specified stopBootOnFault is valid and return the
1815 * stopBootOnFault name associated with that string
1816 *
1817 * @param[in] stopBootOnFaultString String representing the desired
1818 * stopBootOnFault
1819 *
1820 * @return stopBootOnFault value or empty if incoming value is not valid
1821 */
1822inline std::optional<bool>
1823 validstopBootOnFault(const std::string& stopBootOnFaultString)
1824{
1825 if (stopBootOnFaultString == "AnyFault")
1826 {
1827 return true;
1828 }
1829
1830 if (stopBootOnFaultString == "Never")
1831 {
1832 return false;
1833 }
1834
1835 return std::nullopt;
1836}
1837
1838/**
1839 * @brief Sets stopBootOnFault
1840 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001841 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001842 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1843 *
1844 * @return None.
1845 */
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001846inline void
1847 setStopBootOnFault(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1848 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001849{
Ed Tanous62598e32023-07-17 17:06:25 -07001850 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001851
1852 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1853 if (!stopBootEnabled)
1854 {
Ed Tanous62598e32023-07-17 17:06:25 -07001855 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1856 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001857 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001858 "StopBootOnFault");
1859 return;
1860 }
1861
Ginu Georgee93abac2024-06-14 17:35:27 +05301862 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1863 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001864 sdbusplus::message::object_path(
1865 "/xyz/openbmc_project/logging/settings"),
1866 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301867 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001868}
1869
1870/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001871 * @brief Sets automaticRetry (Auto Reboot)
1872 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001873 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills69f35302020-05-17 16:06:31 -05001874 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1875 *
1876 * @return None.
1877 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001878inline void
1879 setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1880 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001881{
Ed Tanous62598e32023-07-17 17:06:25 -07001882 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001883
1884 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001885 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001886
1887 if (automaticRetryConfig == "Disabled")
1888 {
1889 autoRebootEnabled = false;
1890 }
1891 else if (automaticRetryConfig == "RetryAttempts")
1892 {
1893 autoRebootEnabled = true;
1894 }
1895 else
1896 {
Ed Tanous62598e32023-07-17 17:06:25 -07001897 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1898 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001899 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001900 "AutomaticRetryConfig");
1901 return;
1902 }
1903
Ginu Georgee93abac2024-06-14 17:35:27 +05301904 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
1905 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001906 sdbusplus::message::object_path(
1907 "/xyz/openbmc_project/control/host0/auto_reboot"),
1908 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301909 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001910}
1911
Ed Tanous8d69c662023-06-21 10:29:06 -07001912inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1913{
1914 if (policy == "AlwaysOn")
1915 {
1916 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1917 }
1918 if (policy == "AlwaysOff")
1919 {
1920 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1921 }
1922 if (policy == "LastState")
1923 {
1924 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1925 }
1926 return "";
1927}
1928
Gunnar Mills69f35302020-05-17 16:06:31 -05001929/**
George Liuc6a620f2020-04-10 17:18:11 +08001930 * @brief Sets power restore policy properties.
1931 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001932 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001933 * @param[in] policy power restore policy properties from request.
1934 *
1935 * @return None.
1936 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001937inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07001938 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous8d69c662023-06-21 10:29:06 -07001939 std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001940{
Ed Tanous62598e32023-07-17 17:06:25 -07001941 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001942
Ed Tanous8d69c662023-06-21 10:29:06 -07001943 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001944
Ed Tanous8d69c662023-06-21 10:29:06 -07001945 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001946 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001947 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001948 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001949 return;
1950 }
1951
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001952 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301953 asyncResp, "PowerRestorePolicy", "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001954 sdbusplus::message::object_path(
1955 "/xyz/openbmc_project/control/host0/power_restore_policy"),
George Liuc6a620f2020-04-10 17:18:11 +08001956 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301957 powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001958}
1959
AppaRao Pulia6349912019-10-18 17:16:08 +05301960/**
1961 * @brief Retrieves provisioning status
1962 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001963 * @param[in] asyncResp Shared pointer for completing asynchronous
1964 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301965 *
1966 * @return None.
1967 */
Ed Tanous25b54db2024-04-17 15:40:31 -07001968inline void
1969 getProvisioningStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301970{
Ed Tanous62598e32023-07-17 17:06:25 -07001971 BMCWEB_LOG_DEBUG("Get OEM information.");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001972 sdbusplus::asio::getAllProperties(
1973 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1974 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001975 [asyncResp](const boost::system::error_code& ec,
1976 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001977 nlohmann::json& oemPFR =
Ed Tanousac106bf2023-06-07 09:24:59 -07001978 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1979 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
Ed Tanous1d834d42024-07-12 11:38:40 -07001980 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1981 oemPFR["@odata.type"] = "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001982
Ed Tanous002d39b2022-05-31 08:59:27 -07001983 if (ec)
1984 {
Ed Tanous62598e32023-07-17 17:06:25 -07001985 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001986 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07001987 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
1988 FirmwareProvisioningStatus::NotProvisioned;
Ed Tanous002d39b2022-05-31 08:59:27 -07001989 return;
1990 }
1991
1992 const bool* provState = nullptr;
1993 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001994
1995 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001996 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1997 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001998
1999 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002000 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002001 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002002 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002003 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302004
Ed Tanous002d39b2022-05-31 08:59:27 -07002005 if ((provState == nullptr) || (lockState == nullptr))
2006 {
Ed Tanous62598e32023-07-17 17:06:25 -07002007 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
Ed Tanousac106bf2023-06-07 09:24:59 -07002008 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002009 return;
2010 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302011
Ed Tanous25b54db2024-04-17 15:40:31 -07002012 if (*provState)
Ed Tanous002d39b2022-05-31 08:59:27 -07002013 {
Ed Tanous25b54db2024-04-17 15:40:31 -07002014 if (*lockState)
AppaRao Pulia6349912019-10-18 17:16:08 +05302015 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002016 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2017 FirmwareProvisioningStatus::ProvisionedAndLocked;
AppaRao Pulia6349912019-10-18 17:16:08 +05302018 }
2019 else
2020 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002021 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2022 FirmwareProvisioningStatus::ProvisionedButNotLocked;
AppaRao Pulia6349912019-10-18 17:16:08 +05302023 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002024 }
2025 else
2026 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002027 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2028 FirmwareProvisioningStatus::NotProvisioned;
Ed Tanous002d39b2022-05-31 08:59:27 -07002029 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002030 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302031}
AppaRao Pulia6349912019-10-18 17:16:08 +05302032
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302033/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002034 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002035 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002036 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002037 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002038 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002039 */
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002040inline computer_system::PowerMode
2041 translatePowerModeString(const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002042{
Chris Cainb6655102024-02-01 14:35:33 -06002043 using PowerMode = computer_system::PowerMode;
2044
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002045 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002046 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002047 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002048 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002049 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002050 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002051 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002052 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002053 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002054 if (modeString ==
2055 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002056 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002057 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002058 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002059 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002060 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2061 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002062 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002063 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002064 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002065 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2066 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002067 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002068 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002069 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002070 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2071 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002072 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002073 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002074 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002075 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002076 return PowerMode::OEM;
2077 }
2078 // Any other values would be invalid
2079 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2080 return PowerMode::Invalid;
2081}
2082
2083inline void
2084 afterGetPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2085 const boost::system::error_code& ec,
2086 const dbus::utility::DBusPropertiesMap& properties)
2087{
2088 if (ec)
2089 {
2090 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2091 messages::internalError(asyncResp->res);
2092 return;
2093 }
2094
2095 std::string powerMode;
2096 const std::vector<std::string>* allowedModes = nullptr;
2097 const bool success = sdbusplus::unpackPropertiesNoThrow(
2098 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2099 "AllowedPowerModes", allowedModes);
2100
2101 if (!success)
2102 {
2103 messages::internalError(asyncResp->res);
2104 return;
2105 }
2106
2107 nlohmann::json::array_t modeList;
2108 if (allowedModes == nullptr)
2109 {
2110 modeList.emplace_back("Static");
2111 modeList.emplace_back("MaximumPerformance");
2112 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002113 }
2114 else
2115 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002116 for (const auto& aMode : *allowedModes)
2117 {
2118 computer_system::PowerMode modeValue =
2119 translatePowerModeString(aMode);
2120 if (modeValue == computer_system::PowerMode::Invalid)
2121 {
2122 messages::internalError(asyncResp->res);
2123 continue;
2124 }
2125 modeList.emplace_back(modeValue);
2126 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002127 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002128 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002129
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002130 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2131 const computer_system::PowerMode modeValue =
2132 translatePowerModeString(powerMode);
2133 if (modeValue == computer_system::PowerMode::Invalid)
2134 {
2135 messages::internalError(asyncResp->res);
2136 return;
2137 }
2138 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2139}
Chris Cain3a2d04242021-05-28 16:57:10 -05002140/**
2141 * @brief Retrieves system power mode
2142 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002143 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002144 *
2145 * @return None.
2146 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002147inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002148{
Ed Tanous62598e32023-07-17 17:06:25 -07002149 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002150
2151 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002152 constexpr std::array<std::string_view, 1> interfaces = {
2153 "xyz.openbmc_project.Control.Power.Mode"};
2154 dbus::utility::getSubTree(
2155 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002156 [asyncResp](const boost::system::error_code& ec,
2157 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002158 if (ec)
2159 {
Ed Tanous62598e32023-07-17 17:06:25 -07002160 BMCWEB_LOG_DEBUG("DBUS response error on Power.Mode GetSubTree {}",
2161 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002162 // This is an optional D-Bus object so just return if
2163 // error occurs
2164 return;
2165 }
2166 if (subtree.empty())
2167 {
2168 // As noted above, this is an optional interface so just return
2169 // if there is no instance found
2170 return;
2171 }
2172 if (subtree.size() > 1)
2173 {
2174 // More then one PowerMode object is not supported and is an
2175 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002176 BMCWEB_LOG_DEBUG(
2177 "Found more than 1 system D-Bus Power.Mode objects: {}",
2178 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002179 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002180 return;
2181 }
2182 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2183 {
Ed Tanous62598e32023-07-17 17:06:25 -07002184 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002185 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002186 return;
2187 }
2188 const std::string& path = subtree[0].first;
2189 const std::string& service = subtree[0].second.begin()->first;
2190 if (service.empty())
2191 {
Ed Tanous62598e32023-07-17 17:06:25 -07002192 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002193 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002194 return;
2195 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002196
2197 // Valid Power Mode object found, now read the mode properties
2198 sdbusplus::asio::getAllProperties(
Ed Tanous002d39b2022-05-31 08:59:27 -07002199 *crow::connections::systemBus, service, path,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002200 "xyz.openbmc_project.Control.Power.Mode",
Ed Tanousac106bf2023-06-07 09:24:59 -07002201 [asyncResp](const boost::system::error_code& ec2,
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002202 const dbus::utility::DBusPropertiesMap& properties) {
2203 afterGetPowerMode(asyncResp, ec2, properties);
George Liue99073f2022-12-09 11:06:16 +08002204 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002205 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002206}
2207
2208/**
2209 * @brief Validate the specified mode is valid and return the PowerMode
2210 * name associated with that string
2211 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002212 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002213 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002214 *
2215 * @return PowerMode value or empty string if mode is not valid
2216 */
2217inline std::string
Ed Tanousac106bf2023-06-07 09:24:59 -07002218 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cainb6655102024-02-01 14:35:33 -06002219 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002220{
Chris Cainb6655102024-02-01 14:35:33 -06002221 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002222 std::string mode;
2223
Chris Cainb6655102024-02-01 14:35:33 -06002224 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002225 {
2226 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2227 }
Chris Cainb6655102024-02-01 14:35:33 -06002228 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002229 {
George Liu0fda0f12021-11-16 10:06:17 +08002230 mode =
2231 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002232 }
Chris Cainb6655102024-02-01 14:35:33 -06002233 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002234 {
2235 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2236 }
Chris Cainb6655102024-02-01 14:35:33 -06002237 else if (modeValue == PowerMode::BalancedPerformance)
2238 {
2239 mode =
2240 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2241 }
2242 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2243 {
2244 mode =
2245 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2246 }
2247 else if (modeValue == PowerMode::EfficiencyFavorPower)
2248 {
2249 mode =
2250 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2251 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002252 else
2253 {
Chris Cainb6655102024-02-01 14:35:33 -06002254 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002255 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002256 }
2257 return mode;
2258}
2259
2260/**
2261 * @brief Sets system power mode.
2262 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002263 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002264 * @param[in] pmode System power mode from request.
2265 *
2266 * @return None.
2267 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002268inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002269 const std::string& pmode)
2270{
Ed Tanous62598e32023-07-17 17:06:25 -07002271 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002272
Ed Tanousac106bf2023-06-07 09:24:59 -07002273 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002274 if (powerMode.empty())
2275 {
2276 return;
2277 }
2278
2279 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002280 constexpr std::array<std::string_view, 1> interfaces = {
2281 "xyz.openbmc_project.Control.Power.Mode"};
2282 dbus::utility::getSubTree(
2283 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002284 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002285 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002286 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002287 if (ec)
2288 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002289 BMCWEB_LOG_ERROR("DBUS response error on Power.Mode GetSubTree {}",
Ed Tanous62598e32023-07-17 17:06:25 -07002290 ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002291 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002292 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002293 return;
2294 }
2295 if (subtree.empty())
2296 {
2297 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002298 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002299 "PowerMode");
2300 return;
2301 }
2302 if (subtree.size() > 1)
2303 {
2304 // More then one PowerMode object is not supported and is an
2305 // error
Ed Tanous62598e32023-07-17 17:06:25 -07002306 BMCWEB_LOG_DEBUG(
2307 "Found more than 1 system D-Bus Power.Mode objects: {}",
2308 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002309 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002310 return;
2311 }
2312 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2313 {
Ed Tanous62598e32023-07-17 17:06:25 -07002314 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002315 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002316 return;
2317 }
2318 const std::string& path = subtree[0].first;
2319 const std::string& service = subtree[0].second.begin()->first;
2320 if (service.empty())
2321 {
Ed Tanous62598e32023-07-17 17:06:25 -07002322 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002323 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002324 return;
2325 }
2326
Ed Tanous62598e32023-07-17 17:06:25 -07002327 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002328
2329 // Set the Power Mode property
Ginu Georgee93abac2024-06-14 17:35:27 +05302330 setDbusProperty(asyncResp, "PowerMode", service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002331 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05302332 powerMode);
Patrick Williams5a39f772023-10-20 11:20:21 -05002333 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002334}
2335
2336/**
Yong Li51709ff2019-09-30 14:13:04 +08002337 * @brief Translates watchdog timeout action DBUS property value to redfish.
2338 *
2339 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2340 *
2341 * @return Returns as a string, the timeout action in Redfish terms. If
2342 * translation cannot be done, returns an empty string.
2343 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002344inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002345{
2346 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2347 {
2348 return "None";
2349 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002350 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002351 {
2352 return "ResetSystem";
2353 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002354 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002355 {
2356 return "PowerDown";
2357 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002358 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002359 {
2360 return "PowerCycle";
2361 }
2362
2363 return "";
2364}
2365
2366/**
Yong Lic45f0082019-10-10 14:19:01 +08002367 *@brief Translates timeout action from Redfish to DBUS property value.
2368 *
2369 *@param[in] rfAction The timeout action in Redfish.
2370 *
2371 *@return Returns as a string, the time_out action as expected by DBUS.
2372 *If translation cannot be done, returns an empty string.
2373 */
2374
Ed Tanous23a21a12020-07-25 04:45:05 +00002375inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002376{
2377 if (rfAction == "None")
2378 {
2379 return "xyz.openbmc_project.State.Watchdog.Action.None";
2380 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002381 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002382 {
2383 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2384 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002385 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002386 {
2387 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2388 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002389 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002390 {
2391 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2392 }
2393
2394 return "";
2395}
2396
2397/**
Yong Li51709ff2019-09-30 14:13:04 +08002398 * @brief Retrieves host watchdog timer properties over DBUS
2399 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002400 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002401 *
2402 * @return None.
2403 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002404inline void
Ed Tanousac106bf2023-06-07 09:24:59 -07002405 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002406{
Ed Tanous62598e32023-07-17 17:06:25 -07002407 BMCWEB_LOG_DEBUG("Get host watchodg");
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002408 sdbusplus::asio::getAllProperties(
2409 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2410 "/xyz/openbmc_project/watchdog/host0",
2411 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002412 [asyncResp](const boost::system::error_code& ec,
2413 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002414 if (ec)
2415 {
2416 // watchdog service is stopped
Ed Tanous62598e32023-07-17 17:06:25 -07002417 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002418 return;
2419 }
2420
Ed Tanous62598e32023-07-17 17:06:25 -07002421 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002422
2423 nlohmann::json& hostWatchdogTimer =
Ed Tanousac106bf2023-06-07 09:24:59 -07002424 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002425
2426 // watchdog service is running/enabled
Ed Tanous539d8c62024-06-19 14:38:27 -07002427 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002428
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002429 const bool* enabled = nullptr;
2430 const std::string* expireAction = nullptr;
2431
2432 const bool success = sdbusplus::unpackPropertiesNoThrow(
2433 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2434 "ExpireAction", expireAction);
2435
2436 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002437 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002438 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002439 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002440 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002441
2442 if (enabled != nullptr)
2443 {
2444 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2445 }
2446
2447 if (expireAction != nullptr)
2448 {
2449 std::string action = dbusToRfWatchdogAction(*expireAction);
2450 if (action.empty())
2451 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002452 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002453 return;
2454 }
2455 hostWatchdogTimer["TimeoutAction"] = action;
2456 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002457 });
Yong Li51709ff2019-09-30 14:13:04 +08002458}
2459
2460/**
Yong Lic45f0082019-10-10 14:19:01 +08002461 * @brief Sets Host WatchDog Timer properties.
2462 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002463 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002464 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2465 * RF request.
2466 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2467 *
2468 * @return None.
2469 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002470inline void
2471 setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2472 const std::optional<bool> wdtEnable,
2473 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002474{
Ed Tanous62598e32023-07-17 17:06:25 -07002475 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002476
2477 if (wdtTimeOutAction)
2478 {
2479 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2480 // check if TimeOut Action is Valid
2481 if (wdtTimeOutActStr.empty())
2482 {
Ed Tanous62598e32023-07-17 17:06:25 -07002483 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2484 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002485 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002486 "TimeoutAction");
2487 return;
2488 }
2489
Ginu Georgee93abac2024-06-14 17:35:27 +05302490 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2491 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002492 sdbusplus::message::object_path(
2493 "/xyz/openbmc_project/watchdog/host0"),
2494 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302495 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002496 }
2497
2498 if (wdtEnable)
2499 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302500 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2501 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002502 sdbusplus::message::object_path(
2503 "/xyz/openbmc_project/watchdog/host0"),
2504 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302505 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002506 }
2507}
2508
Chris Cain37bbf982021-09-20 10:53:09 -05002509/**
2510 * @brief Parse the Idle Power Saver properties into json
2511 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002512 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002513 * @param[in] properties IPS property data from DBus.
2514 *
2515 * @return true if successful
2516 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002517inline bool
Ed Tanousac106bf2023-06-07 09:24:59 -07002518 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002519 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002520{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002521 const bool* enabled = nullptr;
2522 const uint8_t* enterUtilizationPercent = nullptr;
2523 const uint64_t* enterDwellTime = nullptr;
2524 const uint8_t* exitUtilizationPercent = nullptr;
2525 const uint64_t* exitDwellTime = nullptr;
2526
2527 const bool success = sdbusplus::unpackPropertiesNoThrow(
2528 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002529 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2530 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2531 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002532
2533 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002534 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002535 return false;
2536 }
2537
2538 if (enabled != nullptr)
2539 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002540 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002541 }
2542
2543 if (enterUtilizationPercent != nullptr)
2544 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002545 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002546 *enterUtilizationPercent;
2547 }
2548
2549 if (enterDwellTime != nullptr)
2550 {
2551 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002552 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002553 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2554 .count();
2555 }
2556
2557 if (exitUtilizationPercent != nullptr)
2558 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002559 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002560 *exitUtilizationPercent;
2561 }
2562
2563 if (exitDwellTime != nullptr)
2564 {
2565 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002566 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002567 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2568 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002569 }
2570
2571 return true;
2572}
2573
2574/**
2575 * @brief Retrieves host watchdog timer properties over DBUS
2576 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002577 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002578 *
2579 * @return None.
2580 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002581inline void
2582 getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002583{
Ed Tanous62598e32023-07-17 17:06:25 -07002584 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002585
2586 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002587 constexpr std::array<std::string_view, 1> interfaces = {
2588 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2589 dbus::utility::getSubTree(
2590 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002591 [asyncResp](const boost::system::error_code& ec,
2592 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002593 if (ec)
2594 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002595 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002596 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2597 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002598 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002599 return;
2600 }
2601 if (subtree.empty())
2602 {
2603 // This is an optional interface so just return
2604 // if there is no instance found
Ed Tanous62598e32023-07-17 17:06:25 -07002605 BMCWEB_LOG_DEBUG("No instances found");
Ed Tanous002d39b2022-05-31 08:59:27 -07002606 return;
2607 }
2608 if (subtree.size() > 1)
2609 {
2610 // More then one PowerIdlePowerSaver object is not supported and
2611 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002612 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
2613 "Power.IdlePowerSaver objects: {}",
2614 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002615 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002616 return;
2617 }
2618 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2619 {
Ed Tanous62598e32023-07-17 17:06:25 -07002620 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002621 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002622 return;
2623 }
2624 const std::string& path = subtree[0].first;
2625 const std::string& service = subtree[0].second.begin()->first;
2626 if (service.empty())
2627 {
Ed Tanous62598e32023-07-17 17:06:25 -07002628 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002629 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002630 return;
2631 }
2632
2633 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002634 sdbusplus::asio::getAllProperties(
2635 *crow::connections::systemBus, service, path,
2636 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanousac106bf2023-06-07 09:24:59 -07002637 [asyncResp](const boost::system::error_code& ec2,
2638 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002639 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002640 {
Ed Tanous62598e32023-07-17 17:06:25 -07002641 BMCWEB_LOG_ERROR(
2642 "DBUS response error on IdlePowerSaver GetAll: {}", ec2);
Ed Tanousac106bf2023-06-07 09:24:59 -07002643 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002644 return;
2645 }
2646
Ed Tanousac106bf2023-06-07 09:24:59 -07002647 if (!parseIpsProperties(asyncResp, properties))
Ed Tanous002d39b2022-05-31 08:59:27 -07002648 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002649 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002650 return;
2651 }
George Liue99073f2022-12-09 11:06:16 +08002652 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002653 });
Chris Cain37bbf982021-09-20 10:53:09 -05002654
Ed Tanous62598e32023-07-17 17:06:25 -07002655 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002656}
2657
2658/**
2659 * @brief Sets Idle Power Saver properties.
2660 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002661 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002662 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2663 * RF request.
2664 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2665 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2666 * before entering idle state.
2667 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2668 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2669 * before exiting idle state
2670 *
2671 * @return None.
2672 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002673inline void
2674 setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2675 const std::optional<bool> ipsEnable,
2676 const std::optional<uint8_t> ipsEnterUtil,
2677 const std::optional<uint64_t> ipsEnterTime,
2678 const std::optional<uint8_t> ipsExitUtil,
2679 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002680{
Ed Tanous62598e32023-07-17 17:06:25 -07002681 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002682
2683 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002684 constexpr std::array<std::string_view, 1> interfaces = {
2685 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2686 dbus::utility::getSubTree(
2687 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002688 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002689 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002690 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002691 if (ec)
2692 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002693 BMCWEB_LOG_ERROR(
Ed Tanous62598e32023-07-17 17:06:25 -07002694 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2695 ec);
Ed Tanousac106bf2023-06-07 09:24:59 -07002696 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002697 return;
2698 }
2699 if (subtree.empty())
2700 {
2701 // This is an optional D-Bus object, but user attempted to patch
Ed Tanousac106bf2023-06-07 09:24:59 -07002702 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
Ed Tanous002d39b2022-05-31 08:59:27 -07002703 "IdlePowerSaver");
2704 return;
2705 }
2706 if (subtree.size() > 1)
2707 {
2708 // More then one PowerIdlePowerSaver object is not supported and
2709 // is an error
Ed Tanous62598e32023-07-17 17:06:25 -07002710 BMCWEB_LOG_DEBUG(
2711 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2712 subtree.size());
Ed Tanousac106bf2023-06-07 09:24:59 -07002713 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002714 return;
2715 }
2716 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2717 {
Ed Tanous62598e32023-07-17 17:06:25 -07002718 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002719 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002720 return;
2721 }
2722 const std::string& path = subtree[0].first;
2723 const std::string& service = subtree[0].second.begin()->first;
2724 if (service.empty())
2725 {
Ed Tanous62598e32023-07-17 17:06:25 -07002726 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002727 messages::internalError(asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07002728 return;
2729 }
Chris Cain37bbf982021-09-20 10:53:09 -05002730
Ed Tanous002d39b2022-05-31 08:59:27 -07002731 // Valid Power IdlePowerSaver object found, now set any values that
2732 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002733
Ed Tanous002d39b2022-05-31 08:59:27 -07002734 if (ipsEnable)
2735 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302736 setDbusProperty(asyncResp, "IdlePowerSaver/Enabled", service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002737 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302738 "Enabled", *ipsEnable);
Ed Tanous002d39b2022-05-31 08:59:27 -07002739 }
2740 if (ipsEnterUtil)
2741 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302742 setDbusProperty(asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2743 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002744 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302745 "EnterUtilizationPercent", *ipsEnterUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002746 }
2747 if (ipsEnterTime)
2748 {
2749 // Convert from seconds into milliseconds for DBus
2750 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
Ginu Georgee93abac2024-06-14 17:35:27 +05302751 setDbusProperty(asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds",
2752 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002753 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302754 "EnterDwellTime", timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002755 }
2756 if (ipsExitUtil)
2757 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302758 setDbusProperty(asyncResp, "IdlePowerSaver/ExitUtilizationPercent",
2759 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002760 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302761 "ExitUtilizationPercent", *ipsExitUtil);
Ed Tanous002d39b2022-05-31 08:59:27 -07002762 }
2763 if (ipsExitTime)
2764 {
2765 // Convert from seconds into milliseconds for DBus
2766 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
Ginu Georgee93abac2024-06-14 17:35:27 +05302767 setDbusProperty(asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds",
2768 service, path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002769 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ginu Georgee93abac2024-06-14 17:35:27 +05302770 "ExitDwellTime", timeMilliseconds);
Ed Tanous002d39b2022-05-31 08:59:27 -07002771 }
Patrick Williams5a39f772023-10-20 11:20:21 -05002772 });
Chris Cain37bbf982021-09-20 10:53:09 -05002773
Ed Tanous62598e32023-07-17 17:06:25 -07002774 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002775}
2776
Ed Tanousc1e219d2023-06-07 10:34:33 -07002777inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002778 crow::App& app, const crow::Request& req,
2779 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2780{
2781 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2782 {
2783 return;
2784 }
2785 asyncResp->res.addHeader(
2786 boost::beast::http::field::link,
2787 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2788}
2789
Ed Tanousc1e219d2023-06-07 10:34:33 -07002790inline void handleComputerSystemCollectionGet(
2791 crow::App& app, const crow::Request& req,
2792 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2793{
2794 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2795 {
2796 return;
2797 }
2798
2799 asyncResp->res.addHeader(
2800 boost::beast::http::field::link,
2801 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2802 asyncResp->res.jsonValue["@odata.type"] =
2803 "#ComputerSystemCollection.ComputerSystemCollection";
2804 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2805 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2806
2807 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2808 ifaceArray = nlohmann::json::array();
Ed Tanous25b54db2024-04-17 15:40:31 -07002809 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002810 {
2811 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2812 // Option currently returns no systems. TBD
2813 return;
2814 }
2815 asyncResp->res.jsonValue["Members@odata.count"] = 1;
2816 nlohmann::json::object_t system;
Ed Tanous253f11b2024-05-16 09:38:31 -07002817 system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
2818 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002819 ifaceArray.emplace_back(std::move(system));
2820 sdbusplus::asio::getProperty<std::string>(
2821 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2822 "/xyz/openbmc_project/network/hypervisor",
2823 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
2824 [asyncResp](const boost::system::error_code& ec2,
2825 const std::string& /*hostName*/) {
2826 if (ec2)
2827 {
2828 return;
2829 }
2830 auto val = asyncResp->res.jsonValue.find("Members@odata.count");
2831 if (val == asyncResp->res.jsonValue.end())
2832 {
Ed Tanous62598e32023-07-17 17:06:25 -07002833 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002834 return;
2835 }
Asmitha Karunanithi67b15902024-07-12 12:52:51 -05002836 int64_t* count = val->get_ptr<int64_t*>();
Ed Tanousc1e219d2023-06-07 10:34:33 -07002837 if (count == nullptr)
2838 {
Ed Tanous62598e32023-07-17 17:06:25 -07002839 BMCWEB_LOG_CRITICAL("Count wasn't found??");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002840 return;
2841 }
2842 *count = *count + 1;
Ed Tanous62598e32023-07-17 17:06:25 -07002843 BMCWEB_LOG_DEBUG("Hypervisor is available");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002844 nlohmann::json& ifaceArray2 = asyncResp->res.jsonValue["Members"];
2845 nlohmann::json::object_t hypervisor;
2846 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2847 ifaceArray2.emplace_back(std::move(hypervisor));
Patrick Williams5a39f772023-10-20 11:20:21 -05002848 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07002849}
2850
Yong Lic45f0082019-10-10 14:19:01 +08002851/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002852 * Function transceives data with dbus directly.
2853 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002854inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002855{
Patrick Williams89492a12023-05-10 07:51:34 -05002856 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2857 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2858 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002859 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002860 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002861
2862 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002863 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002864 if (ec)
2865 {
Ed Tanous62598e32023-07-17 17:06:25 -07002866 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002867 messages::internalError(asyncResp->res);
2868 return;
2869 }
2870 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05002871 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002872 serviceName, objectPath, interfaceName, method);
2873}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002874
Ed Tanousc1e219d2023-06-07 10:34:33 -07002875inline void handleComputerSystemResetActionPost(
2876 crow::App& app, const crow::Request& req,
2877 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2878 const std::string& systemName)
2879{
2880 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2881 {
2882 return;
2883 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002884 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002885 {
2886 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2887 systemName);
2888 return;
2889 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002890 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002891 {
2892 // Option currently returns no systems. TBD
2893 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2894 systemName);
2895 return;
2896 }
2897 std::string resetType;
2898 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2899 {
2900 return;
2901 }
2902
2903 // Get the command and host vs. chassis
2904 std::string command;
2905 bool hostCommand = true;
2906 if ((resetType == "On") || (resetType == "ForceOn"))
2907 {
2908 command = "xyz.openbmc_project.State.Host.Transition.On";
2909 hostCommand = true;
2910 }
2911 else if (resetType == "ForceOff")
2912 {
2913 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2914 hostCommand = false;
2915 }
2916 else if (resetType == "ForceRestart")
2917 {
2918 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2919 hostCommand = true;
2920 }
2921 else if (resetType == "GracefulShutdown")
2922 {
2923 command = "xyz.openbmc_project.State.Host.Transition.Off";
2924 hostCommand = true;
2925 }
2926 else if (resetType == "GracefulRestart")
2927 {
2928 command =
2929 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2930 hostCommand = true;
2931 }
2932 else if (resetType == "PowerCycle")
2933 {
2934 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2935 hostCommand = true;
2936 }
2937 else if (resetType == "Nmi")
2938 {
2939 doNMI(asyncResp);
2940 return;
2941 }
2942 else
2943 {
2944 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2945 return;
2946 }
Ed Tanousd02aad32024-02-13 14:43:34 -08002947 sdbusplus::message::object_path statePath("/xyz/openbmc_project/state");
Ed Tanousc1e219d2023-06-07 10:34:33 -07002948
2949 if (hostCommand)
2950 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302951 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Host",
Ed Tanousd02aad32024-02-13 14:43:34 -08002952 statePath / "host0", "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302953 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002954 }
2955 else
2956 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302957 setDbusProperty(asyncResp, "Reset", "xyz.openbmc_project.State.Chassis",
Ed Tanousd02aad32024-02-13 14:43:34 -08002958 statePath / "chassis0",
2959 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302960 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002961 }
2962}
2963
Ed Tanousc1e219d2023-06-07 10:34:33 -07002964inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002965 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002966 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2967 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002968{
2969 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2970 {
2971 return;
2972 }
2973
2974 asyncResp->res.addHeader(
2975 boost::beast::http::field::link,
2976 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2977}
2978
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002979inline void afterPortRequest(
2980 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2981 const boost::system::error_code& ec,
2982 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2983{
2984 if (ec)
2985 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002986 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002987 messages::internalError(asyncResp->res);
2988 return;
2989 }
2990 for (const auto& data : socketData)
2991 {
2992 const std::string& socketPath = get<0>(data);
2993 const std::string& protocolName = get<1>(data);
2994 bool isProtocolEnabled = get<2>(data);
2995 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2996 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2997 // need to retrieve port number for
2998 // obmc-console-ssh service
2999 if (protocolName == "SSH")
3000 {
3001 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003002 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003003 int portNumber) {
3004 if (ec1)
3005 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003006 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003007 messages::internalError(asyncResp->res);
3008 return;
3009 }
3010 nlohmann::json& dataJson1 =
3011 asyncResp->res.jsonValue["SerialConsole"];
3012 dataJson1[protocolName]["Port"] = portNumber;
3013 });
3014 }
3015 }
3016}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003017
3018inline void
3019 handleComputerSystemGet(crow::App& app, const crow::Request& req,
3020 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3021 const std::string& systemName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003022{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003023 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3024 {
3025 return;
3026 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003027
Ed Tanous25b54db2024-04-17 15:40:31 -07003028 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003029 {
3030 // Option currently returns no systems. TBD
3031 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3032 systemName);
3033 return;
3034 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003035
Ed Tanousc1e219d2023-06-07 10:34:33 -07003036 if (systemName == "hypervisor")
3037 {
3038 handleHypervisorSystemGet(asyncResp);
3039 return;
3040 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003041
Ed Tanous253f11b2024-05-16 09:38:31 -07003042 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003043 {
3044 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3045 systemName);
3046 return;
3047 }
3048 asyncResp->res.addHeader(
3049 boost::beast::http::field::link,
3050 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3051 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003052 "#ComputerSystem.v1_22_0.ComputerSystem";
Ed Tanous253f11b2024-05-16 09:38:31 -07003053 asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
3054 asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
Ed Tanous539d8c62024-06-19 14:38:27 -07003055 asyncResp->res.jsonValue["SystemType"] =
3056 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003057 asyncResp->res.jsonValue["Description"] = "Computer System";
3058 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003059 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003060 double(0);
Ed Tanous253f11b2024-05-16 09:38:31 -07003061 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3062 "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous04a258f2018-10-15 08:00:41 -07003063
Ed Tanous253f11b2024-05-16 09:38:31 -07003064 asyncResp->res.jsonValue["Processors"]["@odata.id"] = boost::urls::format(
3065 "/redfish/v1/Systems/{}/Processors", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3066 asyncResp->res.jsonValue["Memory"]["@odata.id"] = boost::urls::format(
3067 "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3068 asyncResp->res.jsonValue["Storage"]["@odata.id"] = boost::urls::format(
3069 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003070 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003071 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3072 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous029573d2019-02-01 10:57:49 -08003073
Ed Tanousc1e219d2023-06-07 10:34:33 -07003074 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003075 boost::urls::format(
3076 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset",
3077 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003078 asyncResp->res
3079 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003080 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3081 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003082
Ed Tanous253f11b2024-05-16 09:38:31 -07003083 asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
3084 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
3085 asyncResp->res.jsonValue["Bios"]["@odata.id"] = boost::urls::format(
3086 "/redfish/v1/Systems/{}/Bios", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003087
Ed Tanousc1e219d2023-06-07 10:34:33 -07003088 nlohmann::json::array_t managedBy;
3089 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003090 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3091 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003092 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003093 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3094 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003095
Ed Tanousc1e219d2023-06-07 10:34:33 -07003096 // Fill in SerialConsole info
3097 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3098 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003099
Ed Tanousc1e219d2023-06-07 10:34:33 -07003100 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3101 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3102 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3103 "Press ~. to exit console";
3104 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3105 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003106
Ed Tanous25b54db2024-04-17 15:40:31 -07003107 if constexpr (BMCWEB_KVM)
3108 {
3109 // Fill in GraphicalConsole info
3110 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3111 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3112 4;
3113 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3114 nlohmann::json::array_t({"KVMIP"});
3115 }
James Feistb49ac872019-05-21 15:12:01 -07003116
Ed Tanousc1e219d2023-06-07 10:34:33 -07003117 getMainChassisId(asyncResp,
3118 [](const std::string& chassisId,
3119 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3120 nlohmann::json::array_t chassisArray;
3121 nlohmann::json& chassis = chassisArray.emplace_back();
3122 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3123 chassisId);
3124 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3125 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003126
George Liu59a17e42022-10-08 09:27:47 +08003127 getSystemLocationIndicatorActive(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003128 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3129 getIndicatorLedState(asyncResp);
Gunnar Mills51bd2d82024-04-01 15:25:51 -05003130 getComputerSystem(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003131 getHostState(asyncResp);
3132 getBootProperties(asyncResp);
3133 getBootProgress(asyncResp);
3134 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati70c4d542023-06-08 04:37:18 -05003135 pcie_util::getPCIeDeviceList(asyncResp,
3136 nlohmann::json::json_pointer("/PCIeDevices"));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003137 getHostWatchdogTimer(asyncResp);
3138 getPowerRestorePolicy(asyncResp);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003139 getStopBootOnFault(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003140 getAutomaticRetryPolicy(asyncResp);
3141 getLastResetTime(asyncResp);
Ed Tanous25b54db2024-04-17 15:40:31 -07003142 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3143 {
3144 getProvisioningStatus(asyncResp);
3145 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003146 getTrustedModuleRequiredToBoot(asyncResp);
3147 getPowerMode(asyncResp);
3148 getIdlePowerSaver(asyncResp);
3149}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003150
Ed Tanousc1e219d2023-06-07 10:34:33 -07003151inline void handleComputerSystemPatch(
3152 crow::App& app, const crow::Request& req,
3153 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3154 const std::string& systemName)
3155{
3156 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3157 {
3158 return;
3159 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003160 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003161 {
3162 // Option currently returns no systems. TBD
3163 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3164 systemName);
3165 return;
3166 }
Ed Tanous253f11b2024-05-16 09:38:31 -07003167 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003168 {
3169 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3170 systemName);
3171 return;
3172 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003173
Ed Tanousc1e219d2023-06-07 10:34:33 -07003174 asyncResp->res.addHeader(
3175 boost::beast::http::field::link,
3176 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003177
Ed Tanousc1e219d2023-06-07 10:34:33 -07003178 std::optional<bool> locationIndicatorActive;
3179 std::optional<std::string> indicatorLed;
3180 std::optional<std::string> assetTag;
3181 std::optional<std::string> powerRestorePolicy;
3182 std::optional<std::string> powerMode;
3183 std::optional<bool> wdtEnable;
3184 std::optional<std::string> wdtTimeOutAction;
3185 std::optional<std::string> bootSource;
3186 std::optional<std::string> bootType;
3187 std::optional<std::string> bootEnable;
3188 std::optional<std::string> bootAutomaticRetry;
3189 std::optional<uint32_t> bootAutomaticRetryAttempts;
3190 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003191 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003192 std::optional<bool> ipsEnable;
3193 std::optional<uint8_t> ipsEnterUtil;
3194 std::optional<uint64_t> ipsEnterTime;
3195 std::optional<uint8_t> ipsExitUtil;
3196 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003197
Ed Tanousc1e219d2023-06-07 10:34:33 -07003198 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003199 if (!json_util::readJsonPatch(
3200 req, asyncResp->res,
3201 "IndicatorLED", indicatorLed,
3202 "LocationIndicatorActive", locationIndicatorActive,
3203 "AssetTag", assetTag,
3204 "PowerRestorePolicy", powerRestorePolicy,
3205 "PowerMode", powerMode,
3206 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3207 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3208 "Boot/BootSourceOverrideTarget", bootSource,
3209 "Boot/BootSourceOverrideMode", bootType,
3210 "Boot/BootSourceOverrideEnabled", bootEnable,
3211 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003212 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003213 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003214 "Boot/StopBootOnFault", stopBootOnFault,
Ed Tanous22d268c2022-05-19 09:39:07 -07003215 "IdlePowerSaver/Enabled", ipsEnable,
3216 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3217 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3218 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3219 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3220 {
3221 return;
3222 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003223 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003224
Ed Tanousc1e219d2023-06-07 10:34:33 -07003225 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003226
Ed Tanousc1e219d2023-06-07 10:34:33 -07003227 if (assetTag)
3228 {
3229 setAssetTag(asyncResp, *assetTag);
3230 }
James Feistb49ac872019-05-21 15:12:01 -07003231
Ed Tanousc1e219d2023-06-07 10:34:33 -07003232 if (wdtEnable || wdtTimeOutAction)
3233 {
3234 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3235 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003236
Ed Tanousc1e219d2023-06-07 10:34:33 -07003237 if (bootSource || bootType || bootEnable)
3238 {
3239 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3240 }
3241 if (bootAutomaticRetry)
3242 {
3243 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3244 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003245
Ed Tanousc1e219d2023-06-07 10:34:33 -07003246 if (bootAutomaticRetryAttempts)
3247 {
3248 setAutomaticRetryAttempts(asyncResp,
3249 bootAutomaticRetryAttempts.value());
3250 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003251
Ed Tanousc1e219d2023-06-07 10:34:33 -07003252 if (bootTrustedModuleRequired)
3253 {
3254 setTrustedModuleRequiredToBoot(asyncResp, *bootTrustedModuleRequired);
3255 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003256
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003257 if (stopBootOnFault)
3258 {
3259 setStopBootOnFault(asyncResp, *stopBootOnFault);
3260 }
3261
Ed Tanousc1e219d2023-06-07 10:34:33 -07003262 if (locationIndicatorActive)
3263 {
George Liu59a17e42022-10-08 09:27:47 +08003264 setSystemLocationIndicatorActive(asyncResp, *locationIndicatorActive);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003265 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003266
Ed Tanousc1e219d2023-06-07 10:34:33 -07003267 // TODO (Gunnar): Remove IndicatorLED after enough time has
3268 // passed
3269 if (indicatorLed)
3270 {
3271 setIndicatorLedState(asyncResp, *indicatorLed);
3272 asyncResp->res.addHeader(boost::beast::http::field::warning,
3273 "299 - \"IndicatorLED is deprecated. Use "
3274 "LocationIndicatorActive instead.\"");
3275 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003276
Ed Tanousc1e219d2023-06-07 10:34:33 -07003277 if (powerRestorePolicy)
3278 {
3279 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3280 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003281
Ed Tanousc1e219d2023-06-07 10:34:33 -07003282 if (powerMode)
3283 {
3284 setPowerMode(asyncResp, *powerMode);
3285 }
Chris Cain37bbf982021-09-20 10:53:09 -05003286
Ed Tanousc1e219d2023-06-07 10:34:33 -07003287 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || ipsExitTime)
3288 {
3289 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3290 ipsExitUtil, ipsExitTime);
3291 }
3292}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303293
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003294inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003295 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003296 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003297 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003298{
3299 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3300 {
3301 return;
3302 }
3303 asyncResp->res.addHeader(
3304 boost::beast::http::field::link,
3305 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3306}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003307
3308/**
3309 * @brief Translates allowed host transitions to redfish string
3310 *
3311 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3312 * @param[out] allowableValues The translated host transition(s)
3313 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303314 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003315 * allowableValues. If translation not possible, does nothing to
3316 * allowableValues.
3317 */
3318inline void
3319 dbusToRfAllowedHostTransitions(const std::string& dbusAllowedHostTran,
3320 nlohmann::json::array_t& allowableValues)
3321{
3322 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3323 {
3324 allowableValues.emplace_back(resource::ResetType::On);
3325 allowableValues.emplace_back(resource::ResetType::ForceOn);
3326 }
3327 else if (dbusAllowedHostTran ==
3328 "xyz.openbmc_project.State.Host.Transition.Off")
3329 {
3330 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3331 }
3332 else if (dbusAllowedHostTran ==
3333 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3334 {
3335 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3336 }
3337 else if (dbusAllowedHostTran ==
3338 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3339 {
3340 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3341 }
3342 else
3343 {
3344 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3345 }
3346}
3347
3348inline void afterGetAllowedHostTransitions(
3349 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3350 const boost::system::error_code& ec,
3351 const std::vector<std::string>& allowedHostTransitions)
3352{
3353 nlohmann::json::array_t allowableValues;
3354
3355 // Supported on all systems currently
3356 allowableValues.emplace_back(resource::ResetType::ForceOff);
3357 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3358 allowableValues.emplace_back(resource::ResetType::Nmi);
3359
3360 if (ec)
3361 {
Ed Tanouse715d142024-03-07 15:47:37 -08003362 if ((ec.value() ==
3363 boost::system::linux_error::bad_request_descriptor) ||
3364 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003365 {
3366 // Property not implemented so just return defaults
3367 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3368 allowableValues.emplace_back(resource::ResetType::On);
3369 allowableValues.emplace_back(resource::ResetType::ForceOn);
3370 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3371 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3372 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3373 }
3374 else
3375 {
3376 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3377 messages::internalError(asyncResp->res);
3378 return;
3379 }
3380 }
3381 else
3382 {
3383 for (const std::string& transition : allowedHostTransitions)
3384 {
3385 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3386 dbusToRfAllowedHostTransitions(transition, allowableValues);
3387 }
3388 }
3389
3390 nlohmann::json::object_t parameter;
3391 parameter["Name"] = "ResetType";
3392 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003393 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003394 parameter["AllowableValues"] = std::move(allowableValues);
3395 nlohmann::json::array_t parameters;
3396 parameters.emplace_back(std::move(parameter));
3397 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3398}
3399
Ed Tanousc1e219d2023-06-07 10:34:33 -07003400inline void handleSystemCollectionResetActionGet(
3401 crow::App& app, const crow::Request& req,
3402 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3403 const std::string& systemName)
3404{
3405 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3406 {
3407 return;
3408 }
Ed Tanous25b54db2024-04-17 15:40:31 -07003409 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003410 {
3411 // Option currently returns no systems. TBD
3412 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3413 systemName);
3414 return;
3415 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003416
Ed Tanousc1e219d2023-06-07 10:34:33 -07003417 if (systemName == "hypervisor")
3418 {
3419 handleHypervisorResetActionGet(asyncResp);
3420 return;
3421 }
3422
Ed Tanous253f11b2024-05-16 09:38:31 -07003423 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003424 {
3425 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3426 systemName);
3427 return;
3428 }
3429
3430 asyncResp->res.addHeader(
3431 boost::beast::http::field::link,
3432 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3433
3434 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003435 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
3436 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003437 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3438 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3439 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3440
Andrew Geissler33e1f122024-02-26 21:10:16 -06003441 // Look to see if system defines AllowedHostTransitions
3442 sdbusplus::asio::getProperty<std::vector<std::string>>(
3443 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
3444 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
3445 "AllowedHostTransitions",
3446 [asyncResp](const boost::system::error_code& ec,
3447 const std::vector<std::string>& allowedHostTransitions) {
3448 afterGetAllowedHostTransitions(asyncResp, ec, allowedHostTransitions);
3449 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003450}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303451/**
3452 * SystemResetActionInfo derived class for delivering Computer Systems
3453 * ResetType AllowableValues using ResetInfo schema.
3454 */
Ed Tanous100afe52023-06-07 13:30:46 -07003455inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303456{
Ed Tanous100afe52023-06-07 13:30:46 -07003457 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3458 .privileges(redfish::privileges::headComputerSystemCollection)
3459 .methods(boost::beast::http::verb::head)(
3460 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3461
3462 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3463 .privileges(redfish::privileges::getComputerSystemCollection)
3464 .methods(boost::beast::http::verb::get)(
3465 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3466
3467 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3468 .privileges(redfish::privileges::headComputerSystem)
3469 .methods(boost::beast::http::verb::head)(
3470 std::bind_front(handleComputerSystemHead, std::ref(app)));
3471
3472 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3473 .privileges(redfish::privileges::getComputerSystem)
3474 .methods(boost::beast::http::verb::get)(
3475 std::bind_front(handleComputerSystemGet, std::ref(app)));
3476
3477 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3478 .privileges(redfish::privileges::patchComputerSystem)
3479 .methods(boost::beast::http::verb::patch)(
3480 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3481
3482 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3483 .privileges(redfish::privileges::postComputerSystem)
3484 .methods(boost::beast::http::verb::post)(std::bind_front(
3485 handleComputerSystemResetActionPost, std::ref(app)));
3486
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003487 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003488 .privileges(redfish::privileges::headActionInfo)
3489 .methods(boost::beast::http::verb::head)(std::bind_front(
3490 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003491 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003492 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003493 .methods(boost::beast::http::verb::get)(std::bind_front(
3494 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003495}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003496} // namespace redfish