blob: 59abd4f026851e26153711a83f4fe589b92b8f03 [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
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070019#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070021#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080022#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080023#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070024#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080025#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "registries/privilege_registry.hpp"
27#include "utils/dbus_utils.hpp"
28#include "utils/json_utils.hpp"
29#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070030#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080031
Ed Tanous9712f8a2018-09-21 13:38:49 -070032#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080033#include <boost/system/error_code.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070034#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020035#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050036
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
38#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080039#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020040
Ed Tanous1abe55e2018-09-05 08:30:59 -070041namespace redfish
42{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020043
Alpana Kumari9d3ae102019-04-12 06:49:32 -050044/**
45 * @brief Updates the Functional State of DIMMs
46 *
47 * @param[in] aResp Shared pointer for completing asynchronous calls
48 * @param[in] dimmState Dimm's Functional state, true/false
49 *
50 * @return None.
51 */
zhanghch058d1b46d2021-04-01 11:18:24 +080052inline void
53 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070054 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070056 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050057
Gunnar Mills4e0453b2020-07-08 14:00:30 -050058 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 // Update STATE only if previous State was DISABLED and current Dimm is
60 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070061 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050062 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
63 if (prevMemSummary == "Disabled")
64 {
Ed Tanouse05aec52022-01-25 10:28:56 -080065 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050066 {
67 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
68 "Enabled";
69 }
70 }
71}
72
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050073/*
74 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
75 *
76 * @param[in] aResp Shared pointer for completing asynchronous calls
77 * @param[in] cpuPresenceState CPU present or not
78 *
79 * @return None.
80 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070081inline void
82 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
83 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050084{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070085 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050086
Ed Tanous55f79e62022-01-25 11:26:16 -080087 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050088 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050089 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080090 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080091 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050092 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080093 if (procCountPtr != nullptr)
94 {
95 // shouldn't be possible to be nullptr
96 *procCountPtr += 1;
97 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050098 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050099}
100
101/*
102 * @brief Update "ProcessorSummary" "Status" "State" based on
103 * CPU Functional State
104 *
105 * @param[in] aResp Shared pointer for completing asynchronous calls
106 * @param[in] cpuFunctionalState is CPU functional true/false
107 *
108 * @return None.
109 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700110inline void
111 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
112 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700114 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500115
Ed Tanous02cad962022-06-30 16:50:15 -0700116 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500117 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
118
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500119 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500120 // Update STATE only if previous State was Non_Functional and current CPU is
121 // Functional.
122 if (prevProcState == "Disabled")
123 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800124 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500125 {
126 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
127 "Enabled";
128 }
129 }
130}
131
Ali Ahmed382d6472021-09-03 16:53:53 -0500132inline void getProcessorProperties(
133 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
134 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
135 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500136{
137
138 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
139
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200140 // TODO: Get Model
141
142 const uint16_t* coreCount = nullptr;
143
144 const bool success = sdbusplus::unpackPropertiesNoThrow(
145 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
146
147 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500148 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200149 messages::internalError(aResp->res);
150 return;
151 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500152
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200153 if (coreCount != nullptr)
154 {
155 nlohmann::json& coreCountJson =
156 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
157 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500158
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200159 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500160 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200161 coreCountJson = *coreCount;
162 }
163 else
164 {
165 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500166 }
167 }
168}
169
170/*
171 * @brief Get ProcessorSummary fields
172 *
173 * @param[in] aResp Shared pointer for completing asynchronous calls
174 * @param[in] service dbus service for Cpu Information
175 * @param[in] path dbus path for Cpu
176 *
177 * @return None.
178 */
179inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
180 const std::string& service,
181 const std::string& path)
182{
183
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800184 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500185 const bool cpuPresenceCheck) {
186 if (ec3)
187 {
188 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
189 return;
190 }
191 modifyCpuPresenceState(aResp, cpuPresenceCheck);
192 };
193
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800194 auto getCpuFunctionalState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500195 const bool cpuFunctionalCheck) {
196 if (ec3)
197 {
198 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
199 return;
200 }
201 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
202 };
203
204 // Get the Presence of CPU
205 sdbusplus::asio::getProperty<bool>(
206 *crow::connections::systemBus, service, path,
207 "xyz.openbmc_project.Inventory.Item", "Present",
208 std::move(getCpuPresenceState));
209
210 // Get the Functional State
211 sdbusplus::asio::getProperty<bool>(
212 *crow::connections::systemBus, service, path,
213 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
214 std::move(getCpuFunctionalState));
215
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200216 sdbusplus::asio::getAllProperties(
217 *crow::connections::systemBus, service, path,
218 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500219 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800220 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800221 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700222 if (ec2)
223 {
224 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
225 messages::internalError(aResp->res);
226 return;
227 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500228 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200229 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500230}
231
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500232/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700233 * @brief Retrieves computer system properties over dbus
234 *
235 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500236 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700237 *
238 * @return None.
239 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700240inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800241 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700242 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700243{
Ed Tanous6c34de42018-08-29 13:37:36 -0700244 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800245 constexpr std::array<std::string_view, 5> interfaces = {
246 "xyz.openbmc_project.Inventory.Decorator.Asset",
247 "xyz.openbmc_project.Inventory.Item.Cpu",
248 "xyz.openbmc_project.Inventory.Item.Dimm",
249 "xyz.openbmc_project.Inventory.Item.System",
250 "xyz.openbmc_project.Common.UUID",
251 };
252 dbus::utility::getSubTree(
253 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800254 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800255 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800256 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700257 if (ec)
258 {
259 BMCWEB_LOG_DEBUG << "DBUS response error";
260 messages::internalError(aResp->res);
261 return;
262 }
263 // Iterate over all retrieved ObjectPaths.
264 for (const std::pair<
265 std::string,
266 std::vector<std::pair<std::string, std::vector<std::string>>>>&
267 object : subtree)
268 {
269 const std::string& path = object.first;
270 BMCWEB_LOG_DEBUG << "Got path: " << path;
271 const std::vector<std::pair<std::string, std::vector<std::string>>>&
272 connectionNames = object.second;
273 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700274 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700275 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700276 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700277
278 auto memoryHealth = std::make_shared<HealthPopulate>(
279 aResp, "/MemorySummary/Status"_json_pointer);
280
281 auto cpuHealth = std::make_shared<HealthPopulate>(
282 aResp, "/ProcessorSummary/Status"_json_pointer);
283
284 systemHealth->children.emplace_back(memoryHealth);
285 systemHealth->children.emplace_back(cpuHealth);
286
287 // This is not system, so check if it's cpu, dimm, UUID or
288 // BiosVer
289 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700290 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700291 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700292 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700293 if (interfaceName ==
294 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700295 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700296 BMCWEB_LOG_DEBUG
297 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500298
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200299 sdbusplus::asio::getAllProperties(
300 *crow::connections::systemBus, connection.first,
301 path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanous002d39b2022-05-31 08:59:27 -0700302 [aResp, service{connection.first},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800303 path](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700304 const dbus::utility::DBusPropertiesMap&
305 properties) {
306 if (ec2)
307 {
308 BMCWEB_LOG_ERROR << "DBUS response error "
309 << ec2;
310 messages::internalError(aResp->res);
311 return;
312 }
313 BMCWEB_LOG_DEBUG << "Got " << properties.size()
314 << " Dimm properties.";
315
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200316 if (properties.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700317 {
318 sdbusplus::asio::getProperty<bool>(
319 *crow::connections::systemBus, service,
320 path,
321 "xyz.openbmc_project.State."
322 "Decorator.OperationalStatus",
323 "Functional",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800324 [aResp](
325 const boost::system::error_code& ec3,
326 bool dimmState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700327 if (ec3)
328 {
329 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000330 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800331 return;
332 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700333 updateDimmProperties(aResp, dimmState);
334 });
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200335 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700336 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200337
338 const uint32_t* memorySizeInKB = nullptr;
339
340 const bool success =
341 sdbusplus::unpackPropertiesNoThrow(
342 dbus_utils::UnpackErrorPrinter(),
343 properties, "MemorySizeInKB",
344 memorySizeInKB);
345
346 if (!success)
347 {
348 messages::internalError(aResp->res);
349 return;
350 }
351
352 if (memorySizeInKB != nullptr)
353 {
354 nlohmann::json& totalMemory =
355 aResp->res
356 .jsonValue["MemorySummary"]
357 ["TotalSystemMemoryGiB"];
358 const uint64_t* preValue =
359 totalMemory.get_ptr<const uint64_t*>();
360 if (preValue == nullptr)
361 {
362 aResp->res
363 .jsonValue["MemorySummary"]
364 ["TotalSystemMemoryGiB"] =
365 *memorySizeInKB / (1024 * 1024);
366 }
367 else
368 {
369 aResp->res
370 .jsonValue["MemorySummary"]
371 ["TotalSystemMemoryGiB"] =
372 *memorySizeInKB / (1024 * 1024) +
373 *preValue;
374 }
375 aResp->res.jsonValue["MemorySummary"]["Status"]
376 ["State"] = "Enabled";
377 }
378 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700379
380 memoryHealth->inventory.emplace_back(path);
381 }
382 else if (interfaceName ==
383 "xyz.openbmc_project.Inventory.Item.Cpu")
384 {
385 BMCWEB_LOG_DEBUG
386 << "Found Cpu, now get its properties.";
387
388 getProcessorSummary(aResp, connection.first, path);
389
390 cpuHealth->inventory.emplace_back(path);
391 }
392 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
393 {
394 BMCWEB_LOG_DEBUG
395 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200396
397 sdbusplus::asio::getAllProperties(
398 *crow::connections::systemBus, connection.first,
399 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800400 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700401 const dbus::utility::DBusPropertiesMap&
402 properties) {
403 if (ec3)
404 {
405 BMCWEB_LOG_DEBUG << "DBUS response error "
406 << ec3;
407 messages::internalError(aResp->res);
408 return;
409 }
410 BMCWEB_LOG_DEBUG << "Got " << properties.size()
411 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700412
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200413 const std::string* uUID = nullptr;
414
415 const bool success =
416 sdbusplus::unpackPropertiesNoThrow(
417 dbus_utils::UnpackErrorPrinter(),
418 properties, "UUID", uUID);
419
420 if (!success)
421 {
422 messages::internalError(aResp->res);
423 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700424 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200425
426 if (uUID != nullptr)
427 {
428 std::string valueStr = *uUID;
429 if (valueStr.size() == 32)
430 {
431 valueStr.insert(8, 1, '-');
432 valueStr.insert(13, 1, '-');
433 valueStr.insert(18, 1, '-');
434 valueStr.insert(23, 1, '-');
435 }
436 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
437 aResp->res.jsonValue["UUID"] = valueStr;
438 }
439 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700440 }
441 else if (interfaceName ==
442 "xyz.openbmc_project.Inventory.Item.System")
443 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200444 sdbusplus::asio::getAllProperties(
445 *crow::connections::systemBus, connection.first,
446 path,
447 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800448 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700449 const dbus::utility::DBusPropertiesMap&
450 propertiesList) {
451 if (ec2)
452 {
453 // doesn't have to include this
454 // interface
455 return;
456 }
457 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
458 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200459
460 const std::string* partNumber = nullptr;
461 const std::string* serialNumber = nullptr;
462 const std::string* manufacturer = nullptr;
463 const std::string* model = nullptr;
464 const std::string* subModel = nullptr;
465
466 const bool success =
467 sdbusplus::unpackPropertiesNoThrow(
468 dbus_utils::UnpackErrorPrinter(),
469 propertiesList, "PartNumber", partNumber,
470 "SerialNumber", serialNumber,
471 "Manufacturer", manufacturer, "Model",
472 model, "SubModel", subModel);
473
474 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700475 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200476 messages::internalError(aResp->res);
477 return;
478 }
479
480 if (partNumber != nullptr)
481 {
482 aResp->res.jsonValue["PartNumber"] =
483 *partNumber;
484 }
485
486 if (serialNumber != nullptr)
487 {
488 aResp->res.jsonValue["SerialNumber"] =
489 *serialNumber;
490 }
491
492 if (manufacturer != nullptr)
493 {
494 aResp->res.jsonValue["Manufacturer"] =
495 *manufacturer;
496 }
497
498 if (model != nullptr)
499 {
500 aResp->res.jsonValue["Model"] = *model;
501 }
502
503 if (subModel != nullptr)
504 {
505 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700506 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500507
Ed Tanous002d39b2022-05-31 08:59:27 -0700508 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700509 sw_util::populateSoftwareInformation(
510 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700511 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200512 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700513
Ed Tanous002d39b2022-05-31 08:59:27 -0700514 sdbusplus::asio::getProperty<std::string>(
515 *crow::connections::systemBus, connection.first,
516 path,
517 "xyz.openbmc_project.Inventory.Decorator."
518 "AssetTag",
519 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800520 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700521 const std::string& value) {
522 if (ec2)
523 {
524 // doesn't have to include this
525 // interface
526 return;
527 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700528
Ed Tanous002d39b2022-05-31 08:59:27 -0700529 aResp->res.jsonValue["AssetTag"] = value;
530 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700531 }
532 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200533 break;
Ed Tanous6c34de42018-08-29 13:37:36 -0700534 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700535 }
Ed Tanous66173382018-08-15 18:20:59 -0700536 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700537}
538
539/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 * @brief Retrieves host state properties over dbus
541 *
542 * @param[in] aResp Shared pointer for completing asynchronous calls.
543 *
544 * @return None.
545 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800546inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700547{
548 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700549 sdbusplus::asio::getProperty<std::string>(
550 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
551 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
552 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800553 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700554 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700555 if (ec)
556 {
557 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700558 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 // Service not available, no error, just don't return
560 // host state info
561 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700562 return;
563 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700564 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
565 messages::internalError(aResp->res);
566 return;
567 }
Ed Tanous66173382018-08-15 18:20:59 -0700568
Ed Tanous002d39b2022-05-31 08:59:27 -0700569 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
570 // Verify Host State
571 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
572 {
573 aResp->res.jsonValue["PowerState"] = "On";
574 aResp->res.jsonValue["Status"]["State"] = "Enabled";
575 }
576 else if (hostState ==
577 "xyz.openbmc_project.State.Host.HostState.Quiesced")
578 {
579 aResp->res.jsonValue["PowerState"] = "On";
580 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
581 }
582 else if (hostState ==
583 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
584 {
585 aResp->res.jsonValue["PowerState"] = "On";
586 aResp->res.jsonValue["Status"]["State"] = "InTest";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOn";
593 aResp->res.jsonValue["Status"]["State"] = "Starting";
594 }
595 else if (hostState ==
596 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
597 {
598 aResp->res.jsonValue["PowerState"] = "PoweringOff";
599 aResp->res.jsonValue["Status"]["State"] = "Disabled";
600 }
601 else
602 {
603 aResp->res.jsonValue["PowerState"] = "Off";
604 aResp->res.jsonValue["Status"]["State"] = "Disabled";
605 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700606 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700607}
608
609/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500610 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530611 *
612 * @param[in] dbusSource The boot source in DBUS speak.
613 *
614 * @return Returns as a string, the boot source in Redfish terms. If translation
615 * cannot be done, returns an empty string.
616 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000617inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530618{
619 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
620 {
621 return "None";
622 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700623 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530624 {
625 return "Hdd";
626 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700627 if (dbusSource ==
628 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530629 {
630 return "Cd";
631 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700632 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530633 {
634 return "Pxe";
635 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700636 if (dbusSource ==
637 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700638 {
639 return "Usb";
640 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700641 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530642}
643
644/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300645 * @brief Translates boot type DBUS property value to redfish.
646 *
647 * @param[in] dbusType The boot type in DBUS speak.
648 *
649 * @return Returns as a string, the boot type in Redfish terms. If translation
650 * cannot be done, returns an empty string.
651 */
652inline std::string dbusToRfBootType(const std::string& dbusType)
653{
654 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
655 {
656 return "Legacy";
657 }
658 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
659 {
660 return "UEFI";
661 }
662 return "";
663}
664
665/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500666 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530667 *
668 * @param[in] dbusMode The boot mode in DBUS speak.
669 *
670 * @return Returns as a string, the boot mode in Redfish terms. If translation
671 * cannot be done, returns an empty string.
672 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000673inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674{
675 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
676 {
677 return "None";
678 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700679 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530680 {
681 return "Diags";
682 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700683 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530684 {
685 return "BiosSetup";
686 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700687 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530688}
689
690/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600691 * @brief Translates boot progress DBUS property value to redfish.
692 *
693 * @param[in] dbusBootProgress The boot progress in DBUS speak.
694 *
695 * @return Returns as a string, the boot progress in Redfish terms. If
696 * translation cannot be done, returns "None".
697 */
698inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
699{
700 // Now convert the D-Bus BootProgress to the appropriate Redfish
701 // enum
702 std::string rfBpLastState = "None";
703 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
704 "ProgressStages.Unspecified")
705 {
706 rfBpLastState = "None";
707 }
708 else if (dbusBootProgress ==
709 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
710 "PrimaryProcInit")
711 {
712 rfBpLastState = "PrimaryProcessorInitializationStarted";
713 }
714 else if (dbusBootProgress ==
715 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
716 "BusInit")
717 {
718 rfBpLastState = "BusInitializationStarted";
719 }
720 else if (dbusBootProgress ==
721 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
722 "MemoryInit")
723 {
724 rfBpLastState = "MemoryInitializationStarted";
725 }
726 else if (dbusBootProgress ==
727 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
728 "SecondaryProcInit")
729 {
730 rfBpLastState = "SecondaryProcessorInitializationStarted";
731 }
732 else if (dbusBootProgress ==
733 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
734 "PCIInit")
735 {
736 rfBpLastState = "PCIResourceConfigStarted";
737 }
738 else if (dbusBootProgress ==
739 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
740 "SystemSetup")
741 {
742 rfBpLastState = "SetupEntered";
743 }
744 else if (dbusBootProgress ==
745 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
746 "SystemInitComplete")
747 {
748 rfBpLastState = "SystemHardwareInitializationComplete";
749 }
750 else if (dbusBootProgress ==
751 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
752 "OSStart")
753 {
754 rfBpLastState = "OSBootStarted";
755 }
756 else if (dbusBootProgress ==
757 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
758 "OSRunning")
759 {
760 rfBpLastState = "OSRunning";
761 }
762 else
763 {
764 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
765 << dbusBootProgress;
766 // Just return the default
767 }
768 return rfBpLastState;
769}
770
771/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500772 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 *
774 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700775 * @param[out] bootSource The DBus source
776 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700778 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530779 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800780inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500781 const std::string& rfSource,
782 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530783{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300784 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
785 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700786
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 if (rfSource == "None")
788 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700789 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530790 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700791 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530792 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700793 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
794 }
795 else if (rfSource == "Hdd")
796 {
797 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
798 }
799 else if (rfSource == "Diags")
800 {
801 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
802 }
803 else if (rfSource == "Cd")
804 {
805 bootSource =
806 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
807 }
808 else if (rfSource == "BiosSetup")
809 {
810 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530811 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700812 else if (rfSource == "Usb")
813 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700814 bootSource =
815 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700816 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530817 else
818 {
George Liu0fda0f12021-11-16 10:06:17 +0800819 BMCWEB_LOG_DEBUG
820 << "Invalid property value for BootSourceOverrideTarget: "
821 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700822 messages::propertyValueNotInList(aResp->res, rfSource,
823 "BootSourceTargetOverride");
824 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530825 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700826 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530827}
Ali Ahmed19817712021-06-29 17:01:52 -0500828
Andrew Geissler978b8802020-11-19 13:36:40 -0600829/**
830 * @brief Retrieves boot progress of the system
831 *
832 * @param[in] aResp Shared pointer for generating response message.
833 *
834 * @return None.
835 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800836inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600837{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700838 sdbusplus::asio::getProperty<std::string>(
839 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
840 "/xyz/openbmc_project/state/host0",
841 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800842 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700843 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700844 if (ec)
845 {
846 // BootProgress is an optional object so just do nothing if
847 // not found
848 return;
849 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600850
Ed Tanous002d39b2022-05-31 08:59:27 -0700851 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600852
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 aResp->res.jsonValue["BootProgress"]["LastState"] =
854 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700855 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600856}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530857
858/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000859 * @brief Retrieves boot progress Last Update of the system
860 *
861 * @param[in] aResp Shared pointer for generating response message.
862 *
863 * @return None.
864 */
865inline void getBootProgressLastStateTime(
866 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
867{
868 sdbusplus::asio::getProperty<uint64_t>(
869 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
870 "/xyz/openbmc_project/state/host0",
871 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800872 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000873 const uint64_t lastStateTime) {
874 if (ec)
875 {
876 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
877 return;
878 }
879
880 // BootProgressLastUpdate is the last time the BootProgress property
881 // was updated. The time is the Epoch time, number of microseconds
882 // since 1 Jan 1970 00::00::00 UTC."
883 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
884 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
885
886 // Convert to ISO 8601 standard
887 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
888 redfish::time_utils::getDateTimeUintUs(lastStateTime);
889 });
890}
891
892/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300893 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300894 *
895 * @param[in] aResp Shared pointer for generating response message.
896 *
897 * @return None.
898 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300899
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300900inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300901{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700902 sdbusplus::asio::getProperty<std::string>(
903 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
904 "/xyz/openbmc_project/control/host0/boot",
905 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800906 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700907 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700908 if (ec)
909 {
910 // not an error, don't have to have the interface
911 return;
912 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300913
Ed Tanous002d39b2022-05-31 08:59:27 -0700914 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300915
Ed Tanous002d39b2022-05-31 08:59:27 -0700916 aResp->res.jsonValue["Boot"]
917 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700918 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300919
Ed Tanous002d39b2022-05-31 08:59:27 -0700920 auto rfType = dbusToRfBootType(bootType);
921 if (rfType.empty())
922 {
923 messages::internalError(aResp->res);
924 return;
925 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300926
Ed Tanous002d39b2022-05-31 08:59:27 -0700927 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700928 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300929}
930
931/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300932 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933 *
934 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530935 *
936 * @return None.
937 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300938
939inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
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 Tanous5e7e2dc2023-02-16 10:37:01 -0800945 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700946 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700947 if (ec)
948 {
949 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
950 messages::internalError(aResp->res);
951 return;
952 }
953
954 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
955
956 aResp->res
957 .jsonValue["Boot"]
958 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
959 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
960
961 if (bootModeStr !=
962 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
963 {
964 auto rfMode = dbusToRfBootMode(bootModeStr);
965 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530966 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700967 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
968 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700970 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700971 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530972}
973
974/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300975 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530976 *
977 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530978 *
979 * @return None.
980 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300981
982inline void
983 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530984{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700985 sdbusplus::asio::getProperty<std::string>(
986 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
987 "/xyz/openbmc_project/control/host0/boot",
988 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800989 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700990 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700991 if (ec)
992 {
993 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000994 if (ec.value() == boost::asio::error::host_unreachable)
995 {
996 return;
997 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700998 messages::internalError(aResp->res);
999 return;
1000 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301001
Ed Tanous002d39b2022-05-31 08:59:27 -07001002 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301003
Ed Tanous002d39b2022-05-31 08:59:27 -07001004 auto rfSource = dbusToRfBootSource(bootSourceStr);
1005 if (!rfSource.empty())
1006 {
1007 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1008 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001009
Ed Tanous002d39b2022-05-31 08:59:27 -07001010 // Get BootMode as BootSourceOverrideTarget is constructed
1011 // from both BootSource and BootMode
1012 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001013 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301014}
1015
1016/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001017 * @brief This functions abstracts all the logic behind getting a
1018 * "BootSourceOverrideEnabled" property from an overall boot override enable
1019 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301020 *
1021 * @param[in] aResp Shared pointer for generating response message.
1022 *
1023 * @return None.
1024 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301025
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001026inline void
1027 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1028 const bool bootOverrideEnableSetting)
1029{
1030 if (!bootOverrideEnableSetting)
1031 {
1032 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1033 return;
1034 }
1035
1036 // If boot source override is enabled, we need to check 'one_time'
1037 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001038 sdbusplus::asio::getProperty<bool>(
1039 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1040 "/xyz/openbmc_project/control/host0/boot/one_time",
1041 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001042 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001043 if (ec)
1044 {
1045 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1046 messages::internalError(aResp->res);
1047 return;
1048 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301049
Ed Tanous002d39b2022-05-31 08:59:27 -07001050 if (oneTimeSetting)
1051 {
1052 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1053 }
1054 else
1055 {
1056 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1057 "Continuous";
1058 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001059 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301060}
1061
1062/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001063 * @brief Retrieves boot override enable over DBUS
1064 *
1065 * @param[in] aResp Shared pointer for generating response message.
1066 *
1067 * @return None.
1068 */
1069
1070inline void
1071 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1072{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001073 sdbusplus::asio::getProperty<bool>(
1074 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1075 "/xyz/openbmc_project/control/host0/boot",
1076 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001077 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001078 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001079 if (ec)
1080 {
1081 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001082 if (ec.value() == boost::asio::error::host_unreachable)
1083 {
1084 return;
1085 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001086 messages::internalError(aResp->res);
1087 return;
1088 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001089
Ed Tanous002d39b2022-05-31 08:59:27 -07001090 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001091 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001092}
1093
1094/**
1095 * @brief Retrieves boot source override properties
1096 *
1097 * @param[in] aResp Shared pointer for generating response message.
1098 *
1099 * @return None.
1100 */
1101inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1102{
1103 BMCWEB_LOG_DEBUG << "Get boot information.";
1104
1105 getBootOverrideSource(aResp);
1106 getBootOverrideType(aResp);
1107 getBootOverrideEnable(aResp);
1108}
1109
1110/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001111 * @brief Retrieves the Last Reset Time
1112 *
1113 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1114 * and power off. Even though this is the "system" Redfish object look at the
1115 * chassis D-Bus interface for the LastStateChangeTime since this has the
1116 * last power operation time.
1117 *
1118 * @param[in] aResp Shared pointer for generating response message.
1119 *
1120 * @return None.
1121 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001122inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001123{
1124 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1125
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001126 sdbusplus::asio::getProperty<uint64_t>(
1127 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1128 "/xyz/openbmc_project/state/chassis0",
1129 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001130 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001131 if (ec)
1132 {
1133 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1134 return;
1135 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001136
Ed Tanous002d39b2022-05-31 08:59:27 -07001137 // LastStateChangeTime is epoch time, in milliseconds
1138 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1139 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001140
Ed Tanous002d39b2022-05-31 08:59:27 -07001141 // Convert to ISO 8601 standard
1142 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001143 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001144 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001145}
1146
1147/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001148 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1149 *
1150 * @param[in] aResp Shared pointer for generating response message.
1151 *
1152 * @return None.
1153 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001154inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001155{
1156 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1157
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001158 sdbusplus::asio::getProperty<bool>(
1159 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1160 "/xyz/openbmc_project/control/host0/auto_reboot",
1161 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001162 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001163 if (ec)
1164 {
1165 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1166 return;
1167 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001168
Ed Tanous002d39b2022-05-31 08:59:27 -07001169 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1170 if (autoRebootEnabled)
1171 {
1172 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1173 "RetryAttempts";
1174 // If AutomaticRetry (AutoReboot) is enabled see how many
1175 // attempts are left
1176 sdbusplus::asio::getProperty<uint32_t>(
1177 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1178 "/xyz/openbmc_project/state/host0",
1179 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1180 "AttemptsLeft",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001181 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07001182 const uint32_t autoRebootAttemptsLeft) {
1183 if (ec2)
1184 {
1185 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1186 return;
1187 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001188
Ed Tanous002d39b2022-05-31 08:59:27 -07001189 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1190 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001191
Ed Tanous002d39b2022-05-31 08:59:27 -07001192 aResp->res
1193 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1194 autoRebootAttemptsLeft;
1195 });
1196 }
1197 else
1198 {
1199 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1200 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001201
Ed Tanous002d39b2022-05-31 08:59:27 -07001202 // Not on D-Bus. Hardcoded here:
1203 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1204 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001205
Ed Tanous002d39b2022-05-31 08:59:27 -07001206 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1207 // and RetryAttempts. OpenBMC only supports Disabled and
1208 // RetryAttempts.
1209 aResp->res.jsonValue["Boot"]
1210 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1211 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001212 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001213}
1214
1215/**
George Liuc6a620f2020-04-10 17:18:11 +08001216 * @brief Retrieves power restore policy over DBUS.
1217 *
1218 * @param[in] aResp Shared pointer for generating response message.
1219 *
1220 * @return None.
1221 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001222inline void
1223 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001224{
1225 BMCWEB_LOG_DEBUG << "Get power restore policy";
1226
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001227 sdbusplus::asio::getProperty<std::string>(
1228 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1229 "/xyz/openbmc_project/control/host0/power_restore_policy",
1230 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001231 [aResp](const boost::system::error_code& ec,
1232 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001233 if (ec)
1234 {
1235 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1236 return;
1237 }
George Liuc6a620f2020-04-10 17:18:11 +08001238
Ed Tanous002d39b2022-05-31 08:59:27 -07001239 const boost::container::flat_map<std::string, std::string> policyMaps = {
1240 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1241 "AlwaysOn"},
1242 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1243 "AlwaysOff"},
1244 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1245 "LastState"},
1246 // Return `AlwaysOff` when power restore policy set to "None"
1247 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1248 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001249
Ed Tanous002d39b2022-05-31 08:59:27 -07001250 auto policyMapsIt = policyMaps.find(policy);
1251 if (policyMapsIt == policyMaps.end())
1252 {
1253 messages::internalError(aResp->res);
1254 return;
1255 }
George Liuc6a620f2020-04-10 17:18:11 +08001256
Ed Tanous002d39b2022-05-31 08:59:27 -07001257 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001258 });
George Liuc6a620f2020-04-10 17:18:11 +08001259}
1260
1261/**
Ali Ahmed19817712021-06-29 17:01:52 -05001262 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1263 * TPM is required for booting the host.
1264 *
1265 * @param[in] aResp Shared pointer for generating response message.
1266 *
1267 * @return None.
1268 */
1269inline void getTrustedModuleRequiredToBoot(
1270 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1271{
1272 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001273 constexpr std::array<std::string_view, 1> interfaces = {
1274 "xyz.openbmc_project.Control.TPM.Policy"};
1275 dbus::utility::getSubTree(
1276 "/", 0, interfaces,
1277 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001278 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001279 if (ec)
1280 {
1281 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1282 << ec;
1283 // This is an optional D-Bus object so just return if
1284 // error occurs
1285 return;
1286 }
1287 if (subtree.empty())
1288 {
1289 // As noted above, this is an optional interface so just return
1290 // if there is no instance found
1291 return;
1292 }
1293
1294 /* When there is more than one TPMEnable object... */
1295 if (subtree.size() > 1)
1296 {
1297 BMCWEB_LOG_DEBUG
1298 << "DBUS response has more than 1 TPM Enable object:"
1299 << subtree.size();
1300 // Throw an internal Error and return
1301 messages::internalError(aResp->res);
1302 return;
1303 }
1304
1305 // Make sure the Dbus response map has a service and objectPath
1306 // field
1307 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1308 {
1309 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1310 messages::internalError(aResp->res);
1311 return;
1312 }
1313
1314 const std::string& path = subtree[0].first;
1315 const std::string& serv = subtree[0].second.begin()->first;
1316
1317 // Valid TPM Enable object found, now reading the current value
1318 sdbusplus::asio::getProperty<bool>(
1319 *crow::connections::systemBus, serv, path,
1320 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001321 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001322 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001323 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001324 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001325 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001326 messages::internalError(aResp->res);
1327 return;
1328 }
1329
Ed Tanous002d39b2022-05-31 08:59:27 -07001330 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001331 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001332 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1333 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001334 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001335 else
1336 {
1337 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1338 "Disabled";
1339 }
1340 });
George Liue99073f2022-12-09 11:06:16 +08001341 });
Ali Ahmed19817712021-06-29 17:01:52 -05001342}
1343
1344/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001345 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1346 * TPM is required for booting the host.
1347 *
1348 * @param[in] aResp Shared pointer for generating response message.
1349 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1350 *
1351 * @return None.
1352 */
1353inline void setTrustedModuleRequiredToBoot(
1354 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1355{
1356 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001357 constexpr std::array<std::string_view, 1> interfaces = {
1358 "xyz.openbmc_project.Control.TPM.Policy"};
1359 dbus::utility::getSubTree(
1360 "/", 0, interfaces,
1361 [aResp,
1362 tpmRequired](const boost::system::error_code& ec,
1363 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001364 if (ec)
1365 {
1366 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1367 << ec;
1368 messages::internalError(aResp->res);
1369 return;
1370 }
1371 if (subtree.empty())
1372 {
1373 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1374 "TrustedModuleRequiredToBoot");
1375 return;
1376 }
1377
1378 /* When there is more than one TPMEnable object... */
1379 if (subtree.size() > 1)
1380 {
1381 BMCWEB_LOG_DEBUG
1382 << "DBUS response has more than 1 TPM Enable object:"
1383 << subtree.size();
1384 // Throw an internal Error and return
1385 messages::internalError(aResp->res);
1386 return;
1387 }
1388
1389 // Make sure the Dbus response map has a service and objectPath
1390 // field
1391 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1392 {
1393 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1394 messages::internalError(aResp->res);
1395 return;
1396 }
1397
1398 const std::string& path = subtree[0].first;
1399 const std::string& serv = subtree[0].second.begin()->first;
1400
1401 if (serv.empty())
1402 {
1403 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1404 messages::internalError(aResp->res);
1405 return;
1406 }
1407
1408 // Valid TPM Enable object found, now setting the value
1409 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001410 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001411 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001412 {
1413 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001414 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001415 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001416 messages::internalError(aResp->res);
1417 return;
1418 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001419 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1420 },
1421 serv, path, "org.freedesktop.DBus.Properties", "Set",
1422 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1423 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001424 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001425}
1426
1427/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301428 * @brief Sets boot properties into DBUS object(s).
1429 *
1430 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001431 * @param[in] bootType The boot type to set.
1432 * @return Integer error code.
1433 */
1434inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001435 const std::optional<std::string>& bootType)
1436{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001437 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001438
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001439 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001440 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001441 return;
1442 }
1443
1444 // Source target specified
1445 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1446 // Figure out which DBUS interface and property to use
1447 if (*bootType == "Legacy")
1448 {
1449 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1450 }
1451 else if (*bootType == "UEFI")
1452 {
1453 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1454 }
1455 else
1456 {
1457 BMCWEB_LOG_DEBUG << "Invalid property value for "
1458 "BootSourceOverrideMode: "
1459 << *bootType;
1460 messages::propertyValueNotInList(aResp->res, *bootType,
1461 "BootSourceOverrideMode");
1462 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001463 }
1464
1465 // Act on validated parameters
1466 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1467
1468 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001469 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001470 if (ec)
1471 {
1472 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1473 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001474 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001475 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001476 return;
1477 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001478 messages::internalError(aResp->res);
1479 return;
1480 }
1481 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001482 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001483 "xyz.openbmc_project.Settings",
1484 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001485 "org.freedesktop.DBus.Properties", "Set",
1486 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001487 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001488}
1489
1490/**
1491 * @brief Sets boot properties into DBUS object(s).
1492 *
1493 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001494 * @param[in] bootType The boot type to set.
1495 * @return Integer error code.
1496 */
1497inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1498 const std::optional<std::string>& bootEnable)
1499{
1500 if (!bootEnable)
1501 {
1502 return;
1503 }
1504 // Source target specified
1505 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1506
1507 bool bootOverrideEnable = false;
1508 bool bootOverridePersistent = false;
1509 // Figure out which DBUS interface and property to use
1510 if (*bootEnable == "Disabled")
1511 {
1512 bootOverrideEnable = false;
1513 }
1514 else if (*bootEnable == "Once")
1515 {
1516 bootOverrideEnable = true;
1517 bootOverridePersistent = false;
1518 }
1519 else if (*bootEnable == "Continuous")
1520 {
1521 bootOverrideEnable = true;
1522 bootOverridePersistent = true;
1523 }
1524 else
1525 {
George Liu0fda0f12021-11-16 10:06:17 +08001526 BMCWEB_LOG_DEBUG
1527 << "Invalid property value for BootSourceOverrideEnabled: "
1528 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001529 messages::propertyValueNotInList(aResp->res, *bootEnable,
1530 "BootSourceOverrideEnabled");
1531 return;
1532 }
1533
1534 // Act on validated parameters
1535 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1536
1537 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001538 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001539 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001540 {
Ed Tanous8a592812022-06-04 09:06:59 -07001541 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001542 messages::internalError(aResp->res);
1543 return;
1544 }
1545 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001546 },
1547 "xyz.openbmc_project.Settings",
1548 "/xyz/openbmc_project/control/host0/boot",
1549 "org.freedesktop.DBus.Properties", "Set",
1550 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001551 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001552
1553 if (!bootOverrideEnable)
1554 {
1555 return;
1556 }
1557
1558 // In case boot override is enabled we need to set correct value for the
1559 // 'one_time' enable DBus interface
1560 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1561 << bootOverridePersistent;
1562
1563 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001564 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001565 if (ec)
1566 {
1567 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1568 messages::internalError(aResp->res);
1569 return;
1570 }
1571 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001572 },
1573 "xyz.openbmc_project.Settings",
1574 "/xyz/openbmc_project/control/host0/boot/one_time",
1575 "org.freedesktop.DBus.Properties", "Set",
1576 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001577 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001578}
1579
1580/**
1581 * @brief Sets boot properties into DBUS object(s).
1582 *
1583 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301584 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301585 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001586 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301587 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001588inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001589 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301590{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001591 std::string bootSourceStr;
1592 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001593
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001594 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301595 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001596 return;
1597 }
1598
1599 // Source target specified
1600 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1601 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001602 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1603 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001604 {
1605 BMCWEB_LOG_DEBUG
1606 << "Invalid property value for BootSourceOverrideTarget: "
1607 << *bootSource;
1608 messages::propertyValueNotInList(aResp->res, *bootSource,
1609 "BootSourceTargetOverride");
1610 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001611 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301612
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001613 // Act on validated parameters
1614 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1615 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001616
1617 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001618 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001619 if (ec)
1620 {
1621 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1622 messages::internalError(aResp->res);
1623 return;
1624 }
1625 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001626 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001627 "xyz.openbmc_project.Settings",
1628 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001629 "org.freedesktop.DBus.Properties", "Set",
1630 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001631 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001632
1633 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001634 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001635 if (ec)
1636 {
1637 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1638 messages::internalError(aResp->res);
1639 return;
1640 }
1641 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001642 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001643 "xyz.openbmc_project.Settings",
1644 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001645 "org.freedesktop.DBus.Properties", "Set",
1646 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001647 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001648}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001649
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001650/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001651 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301652 *
1653 * @param[in] aResp Shared pointer for generating response message.
1654 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001655 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301656 * @param[in] bootEnable The boot override enable from incoming RF request.
1657 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001658 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301659 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001660
1661inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1662 const std::optional<std::string>& bootSource,
1663 const std::optional<std::string>& bootType,
1664 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301665{
1666 BMCWEB_LOG_DEBUG << "Set boot information.";
1667
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001668 setBootModeOrSource(aResp, bootSource);
1669 setBootType(aResp, bootType);
1670 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301671}
1672
George Liuc6a620f2020-04-10 17:18:11 +08001673/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001674 * @brief Sets AssetTag
1675 *
1676 * @param[in] aResp Shared pointer for generating response message.
1677 * @param[in] assetTag "AssetTag" from request.
1678 *
1679 * @return None.
1680 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001681inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001682 const std::string& assetTag)
1683{
George Liue99073f2022-12-09 11:06:16 +08001684 constexpr std::array<std::string_view, 1> interfaces = {
1685 "xyz.openbmc_project.Inventory.Item.System"};
1686 dbus::utility::getSubTree(
1687 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001688 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001689 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001690 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001691 if (ec)
1692 {
1693 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1694 messages::internalError(aResp->res);
1695 return;
1696 }
1697 if (subtree.empty())
1698 {
1699 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1700 messages::internalError(aResp->res);
1701 return;
1702 }
1703 // Assume only 1 system D-Bus object
1704 // Throw an error if there is more than 1
1705 if (subtree.size() > 1)
1706 {
1707 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1708 messages::internalError(aResp->res);
1709 return;
1710 }
1711 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1712 {
1713 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1714 messages::internalError(aResp->res);
1715 return;
1716 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001717
Ed Tanous002d39b2022-05-31 08:59:27 -07001718 const std::string& path = subtree[0].first;
1719 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001720
Ed Tanous002d39b2022-05-31 08:59:27 -07001721 if (service.empty())
1722 {
1723 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1724 messages::internalError(aResp->res);
1725 return;
1726 }
1727
1728 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001729 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001730 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001731 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001732 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1733 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001734 messages::internalError(aResp->res);
1735 return;
1736 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001737 },
1738 service, path, "org.freedesktop.DBus.Properties", "Set",
1739 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1740 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001741 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001742}
1743
1744/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001745 * @brief Sets automaticRetry (Auto Reboot)
1746 *
1747 * @param[in] aResp Shared pointer for generating response message.
1748 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1749 *
1750 * @return None.
1751 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001752inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001753 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001754{
1755 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1756
1757 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001758 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001759
1760 if (automaticRetryConfig == "Disabled")
1761 {
1762 autoRebootEnabled = false;
1763 }
1764 else if (automaticRetryConfig == "RetryAttempts")
1765 {
1766 autoRebootEnabled = true;
1767 }
1768 else
1769 {
George Liu0fda0f12021-11-16 10:06:17 +08001770 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001771 << automaticRetryConfig;
1772 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1773 "AutomaticRetryConfig");
1774 return;
1775 }
1776
1777 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001778 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001779 if (ec)
1780 {
1781 messages::internalError(aResp->res);
1782 return;
1783 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001784 },
1785 "xyz.openbmc_project.Settings",
1786 "/xyz/openbmc_project/control/host0/auto_reboot",
1787 "org.freedesktop.DBus.Properties", "Set",
1788 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001789 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001790}
1791
1792/**
George Liuc6a620f2020-04-10 17:18:11 +08001793 * @brief Sets power restore policy properties.
1794 *
1795 * @param[in] aResp Shared pointer for generating response message.
1796 * @param[in] policy power restore policy properties from request.
1797 *
1798 * @return None.
1799 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001800inline void
1801 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1802 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001803{
1804 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1805
1806 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001807 {"AlwaysOn",
1808 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1809 {"AlwaysOff",
1810 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1811 {"LastState",
1812 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001813
1814 std::string powerRestorPolicy;
1815
Gunnar Mills4e69c902021-01-05 19:50:11 -06001816 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001817 if (policyMapsIt == policyMaps.end())
1818 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001819 messages::propertyValueNotInList(aResp->res, policy,
1820 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001821 return;
1822 }
1823
1824 powerRestorPolicy = policyMapsIt->second;
1825
1826 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001827 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001828 if (ec)
1829 {
1830 messages::internalError(aResp->res);
1831 return;
1832 }
George Liuc6a620f2020-04-10 17:18:11 +08001833 },
1834 "xyz.openbmc_project.Settings",
1835 "/xyz/openbmc_project/control/host0/power_restore_policy",
1836 "org.freedesktop.DBus.Properties", "Set",
1837 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001838 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001839}
1840
AppaRao Pulia6349912019-10-18 17:16:08 +05301841#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1842/**
1843 * @brief Retrieves provisioning status
1844 *
1845 * @param[in] aResp Shared pointer for completing asynchronous calls.
1846 *
1847 * @return None.
1848 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001849inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301850{
1851 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001852 sdbusplus::asio::getAllProperties(
1853 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1854 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001855 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001856 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001857 nlohmann::json& oemPFR =
1858 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1859 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1860 "#OemComputerSystem.OpenBmc";
1861 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001862
Ed Tanous002d39b2022-05-31 08:59:27 -07001863 if (ec)
1864 {
1865 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1866 // not an error, don't have to have the interface
1867 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1868 return;
1869 }
1870
1871 const bool* provState = nullptr;
1872 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001873
1874 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001875 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1876 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001877
1878 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001879 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001880 messages::internalError(aResp->res);
1881 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001882 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301883
Ed Tanous002d39b2022-05-31 08:59:27 -07001884 if ((provState == nullptr) || (lockState == nullptr))
1885 {
1886 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1887 messages::internalError(aResp->res);
1888 return;
1889 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301890
Ed Tanous002d39b2022-05-31 08:59:27 -07001891 if (*provState == true)
1892 {
1893 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301894 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001895 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301896 }
1897 else
1898 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001899 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301900 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001901 }
1902 else
1903 {
1904 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1905 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001906 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301907}
1908#endif
1909
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301910/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001911 * @brief Translate the PowerMode to a response message.
1912 *
1913 * @param[in] aResp Shared pointer for generating response message.
1914 * @param[in] modeValue PowerMode value to be translated
1915 *
1916 * @return None.
1917 */
1918inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1919 const std::string& modeValue)
1920{
George Liu0fda0f12021-11-16 10:06:17 +08001921 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001922 {
1923 aResp->res.jsonValue["PowerMode"] = "Static";
1924 }
George Liu0fda0f12021-11-16 10:06:17 +08001925 else if (
1926 modeValue ==
1927 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001928 {
1929 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1930 }
George Liu0fda0f12021-11-16 10:06:17 +08001931 else if (modeValue ==
1932 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001933 {
1934 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1935 }
George Liu0fda0f12021-11-16 10:06:17 +08001936 else if (modeValue ==
1937 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001938 {
1939 aResp->res.jsonValue["PowerMode"] = "OEM";
1940 }
1941 else
1942 {
1943 // Any other values would be invalid
1944 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1945 messages::internalError(aResp->res);
1946 }
1947}
1948
1949/**
1950 * @brief Retrieves system power mode
1951 *
1952 * @param[in] aResp Shared pointer for generating response message.
1953 *
1954 * @return None.
1955 */
1956inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1957{
1958 BMCWEB_LOG_DEBUG << "Get power mode.";
1959
1960 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08001961 constexpr std::array<std::string_view, 1> interfaces = {
1962 "xyz.openbmc_project.Control.Power.Mode"};
1963 dbus::utility::getSubTree(
1964 "/", 0, interfaces,
1965 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001966 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001967 if (ec)
1968 {
1969 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
1970 << ec;
1971 // This is an optional D-Bus object so just return if
1972 // error occurs
1973 return;
1974 }
1975 if (subtree.empty())
1976 {
1977 // As noted above, this is an optional interface so just return
1978 // if there is no instance found
1979 return;
1980 }
1981 if (subtree.size() > 1)
1982 {
1983 // More then one PowerMode object is not supported and is an
1984 // error
1985 BMCWEB_LOG_DEBUG
1986 << "Found more than 1 system D-Bus Power.Mode objects: "
1987 << subtree.size();
1988 messages::internalError(aResp->res);
1989 return;
1990 }
1991 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1992 {
1993 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1994 messages::internalError(aResp->res);
1995 return;
1996 }
1997 const std::string& path = subtree[0].first;
1998 const std::string& service = subtree[0].second.begin()->first;
1999 if (service.empty())
2000 {
2001 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2002 messages::internalError(aResp->res);
2003 return;
2004 }
2005 // Valid Power Mode object found, now read the current value
2006 sdbusplus::asio::getProperty<std::string>(
2007 *crow::connections::systemBus, service, path,
2008 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002009 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002010 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002011 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002012 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002013 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002014 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002015 messages::internalError(aResp->res);
2016 return;
2017 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002018
Ed Tanous002d39b2022-05-31 08:59:27 -07002019 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2020 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002021
Ed Tanous002d39b2022-05-31 08:59:27 -07002022 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2023 translatePowerMode(aResp, pmode);
2024 });
George Liue99073f2022-12-09 11:06:16 +08002025 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002026}
2027
2028/**
2029 * @brief Validate the specified mode is valid and return the PowerMode
2030 * name associated with that string
2031 *
2032 * @param[in] aResp Shared pointer for generating response message.
2033 * @param[in] modeString String representing the desired PowerMode
2034 *
2035 * @return PowerMode value or empty string if mode is not valid
2036 */
2037inline std::string
2038 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2039 const std::string& modeString)
2040{
2041 std::string mode;
2042
2043 if (modeString == "Static")
2044 {
2045 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2046 }
2047 else if (modeString == "MaximumPerformance")
2048 {
George Liu0fda0f12021-11-16 10:06:17 +08002049 mode =
2050 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002051 }
2052 else if (modeString == "PowerSaving")
2053 {
2054 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2055 }
2056 else
2057 {
2058 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2059 }
2060 return mode;
2061}
2062
2063/**
2064 * @brief Sets system power mode.
2065 *
2066 * @param[in] aResp Shared pointer for generating response message.
2067 * @param[in] pmode System power mode from request.
2068 *
2069 * @return None.
2070 */
2071inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2072 const std::string& pmode)
2073{
2074 BMCWEB_LOG_DEBUG << "Set power mode.";
2075
2076 std::string powerMode = validatePowerMode(aResp, pmode);
2077 if (powerMode.empty())
2078 {
2079 return;
2080 }
2081
2082 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002083 constexpr std::array<std::string_view, 1> interfaces = {
2084 "xyz.openbmc_project.Control.Power.Mode"};
2085 dbus::utility::getSubTree(
2086 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002087 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002088 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002089 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002090 if (ec)
2091 {
2092 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2093 << ec;
2094 // This is an optional D-Bus object, but user attempted to patch
2095 messages::internalError(aResp->res);
2096 return;
2097 }
2098 if (subtree.empty())
2099 {
2100 // This is an optional D-Bus object, but user attempted to patch
2101 messages::resourceNotFound(aResp->res, "ComputerSystem",
2102 "PowerMode");
2103 return;
2104 }
2105 if (subtree.size() > 1)
2106 {
2107 // More then one PowerMode object is not supported and is an
2108 // error
2109 BMCWEB_LOG_DEBUG
2110 << "Found more than 1 system D-Bus Power.Mode objects: "
2111 << subtree.size();
2112 messages::internalError(aResp->res);
2113 return;
2114 }
2115 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2116 {
2117 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2118 messages::internalError(aResp->res);
2119 return;
2120 }
2121 const std::string& path = subtree[0].first;
2122 const std::string& service = subtree[0].second.begin()->first;
2123 if (service.empty())
2124 {
2125 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2126 messages::internalError(aResp->res);
2127 return;
2128 }
2129
2130 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2131 << path;
2132
2133 // Set the Power Mode property
2134 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002135 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002136 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002137 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002138 messages::internalError(aResp->res);
2139 return;
2140 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002141 },
2142 service, path, "org.freedesktop.DBus.Properties", "Set",
2143 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2144 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002145 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002146}
2147
2148/**
Yong Li51709ff2019-09-30 14:13:04 +08002149 * @brief Translates watchdog timeout action DBUS property value to redfish.
2150 *
2151 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2152 *
2153 * @return Returns as a string, the timeout action in Redfish terms. If
2154 * translation cannot be done, returns an empty string.
2155 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002156inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002157{
2158 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2159 {
2160 return "None";
2161 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002162 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002163 {
2164 return "ResetSystem";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002167 {
2168 return "PowerDown";
2169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002170 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002171 {
2172 return "PowerCycle";
2173 }
2174
2175 return "";
2176}
2177
2178/**
Yong Lic45f0082019-10-10 14:19:01 +08002179 *@brief Translates timeout action from Redfish to DBUS property value.
2180 *
2181 *@param[in] rfAction The timeout action in Redfish.
2182 *
2183 *@return Returns as a string, the time_out action as expected by DBUS.
2184 *If translation cannot be done, returns an empty string.
2185 */
2186
Ed Tanous23a21a12020-07-25 04:45:05 +00002187inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002188{
2189 if (rfAction == "None")
2190 {
2191 return "xyz.openbmc_project.State.Watchdog.Action.None";
2192 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002193 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002194 {
2195 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2196 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002197 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002198 {
2199 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2200 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002201 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002202 {
2203 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2204 }
2205
2206 return "";
2207}
2208
2209/**
Yong Li51709ff2019-09-30 14:13:04 +08002210 * @brief Retrieves host watchdog timer properties over DBUS
2211 *
2212 * @param[in] aResp Shared pointer for completing asynchronous calls.
2213 *
2214 * @return None.
2215 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002216inline void
2217 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002218{
2219 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002220 sdbusplus::asio::getAllProperties(
2221 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2222 "/xyz/openbmc_project/watchdog/host0",
2223 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002224 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002225 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002226 if (ec)
2227 {
2228 // watchdog service is stopped
2229 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2230 return;
2231 }
2232
2233 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2234
2235 nlohmann::json& hostWatchdogTimer =
2236 aResp->res.jsonValue["HostWatchdogTimer"];
2237
2238 // watchdog service is running/enabled
2239 hostWatchdogTimer["Status"]["State"] = "Enabled";
2240
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002241 const bool* enabled = nullptr;
2242 const std::string* expireAction = nullptr;
2243
2244 const bool success = sdbusplus::unpackPropertiesNoThrow(
2245 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2246 "ExpireAction", expireAction);
2247
2248 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002249 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002250 messages::internalError(aResp->res);
2251 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002252 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002253
2254 if (enabled != nullptr)
2255 {
2256 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2257 }
2258
2259 if (expireAction != nullptr)
2260 {
2261 std::string action = dbusToRfWatchdogAction(*expireAction);
2262 if (action.empty())
2263 {
2264 messages::internalError(aResp->res);
2265 return;
2266 }
2267 hostWatchdogTimer["TimeoutAction"] = action;
2268 }
2269 });
Yong Li51709ff2019-09-30 14:13:04 +08002270}
2271
2272/**
Yong Lic45f0082019-10-10 14:19:01 +08002273 * @brief Sets Host WatchDog Timer properties.
2274 *
2275 * @param[in] aResp Shared pointer for generating response message.
2276 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2277 * RF request.
2278 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2279 *
2280 * @return None.
2281 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002282inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002283 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002284 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002285{
2286 BMCWEB_LOG_DEBUG << "Set host watchdog";
2287
2288 if (wdtTimeOutAction)
2289 {
2290 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2291 // check if TimeOut Action is Valid
2292 if (wdtTimeOutActStr.empty())
2293 {
2294 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2295 << *wdtTimeOutAction;
2296 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2297 "TimeoutAction");
2298 return;
2299 }
2300
2301 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002302 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002303 if (ec)
2304 {
2305 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2306 messages::internalError(aResp->res);
2307 return;
2308 }
Yong Lic45f0082019-10-10 14:19:01 +08002309 },
2310 "xyz.openbmc_project.Watchdog",
2311 "/xyz/openbmc_project/watchdog/host0",
2312 "org.freedesktop.DBus.Properties", "Set",
2313 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002314 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002315 }
2316
2317 if (wdtEnable)
2318 {
2319 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002320 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002321 if (ec)
2322 {
2323 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2324 messages::internalError(aResp->res);
2325 return;
2326 }
Yong Lic45f0082019-10-10 14:19:01 +08002327 },
2328 "xyz.openbmc_project.Watchdog",
2329 "/xyz/openbmc_project/watchdog/host0",
2330 "org.freedesktop.DBus.Properties", "Set",
2331 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002332 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002333 }
2334}
2335
Chris Cain37bbf982021-09-20 10:53:09 -05002336/**
2337 * @brief Parse the Idle Power Saver properties into json
2338 *
2339 * @param[in] aResp Shared pointer for completing asynchronous calls.
2340 * @param[in] properties IPS property data from DBus.
2341 *
2342 * @return true if successful
2343 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002344inline bool
2345 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2346 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002347{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002348 const bool* enabled = nullptr;
2349 const uint8_t* enterUtilizationPercent = nullptr;
2350 const uint64_t* enterDwellTime = nullptr;
2351 const uint8_t* exitUtilizationPercent = nullptr;
2352 const uint64_t* exitDwellTime = nullptr;
2353
2354 const bool success = sdbusplus::unpackPropertiesNoThrow(
2355 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2356 "EnterUtilizationPercent", enterUtilizationPercent,
2357 "ExitUtilizationPercent", exitUtilizationPercent, "ExitDwellTime",
2358 exitDwellTime);
2359
2360 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002361 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002362 return false;
2363 }
2364
2365 if (enabled != nullptr)
2366 {
2367 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2368 }
2369
2370 if (enterUtilizationPercent != nullptr)
2371 {
2372 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2373 *enterUtilizationPercent;
2374 }
2375
2376 if (enterDwellTime != nullptr)
2377 {
2378 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2379 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2380 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2381 .count();
2382 }
2383
2384 if (exitUtilizationPercent != nullptr)
2385 {
2386 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2387 *exitUtilizationPercent;
2388 }
2389
2390 if (exitDwellTime != nullptr)
2391 {
2392 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2393 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2394 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2395 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002396 }
2397
2398 return true;
2399}
2400
2401/**
2402 * @brief Retrieves host watchdog timer properties over DBUS
2403 *
2404 * @param[in] aResp Shared pointer for completing asynchronous calls.
2405 *
2406 * @return None.
2407 */
2408inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2409{
2410 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2411
2412 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002413 constexpr std::array<std::string_view, 1> interfaces = {
2414 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2415 dbus::utility::getSubTree(
2416 "/", 0, interfaces,
2417 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002418 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002419 if (ec)
2420 {
2421 BMCWEB_LOG_DEBUG
2422 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2423 << ec;
2424 messages::internalError(aResp->res);
2425 return;
2426 }
2427 if (subtree.empty())
2428 {
2429 // This is an optional interface so just return
2430 // if there is no instance found
2431 BMCWEB_LOG_DEBUG << "No instances found";
2432 return;
2433 }
2434 if (subtree.size() > 1)
2435 {
2436 // More then one PowerIdlePowerSaver object is not supported and
2437 // is an error
2438 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2439 "Power.IdlePowerSaver objects: "
2440 << subtree.size();
2441 messages::internalError(aResp->res);
2442 return;
2443 }
2444 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2445 {
2446 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2447 messages::internalError(aResp->res);
2448 return;
2449 }
2450 const std::string& path = subtree[0].first;
2451 const std::string& service = subtree[0].second.begin()->first;
2452 if (service.empty())
2453 {
2454 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2455 messages::internalError(aResp->res);
2456 return;
2457 }
2458
2459 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002460 sdbusplus::asio::getAllProperties(
2461 *crow::connections::systemBus, service, path,
2462 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002463 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002464 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002465 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002466 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002467 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002468 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002469 messages::internalError(aResp->res);
2470 return;
2471 }
2472
Ed Tanous002d39b2022-05-31 08:59:27 -07002473 if (!parseIpsProperties(aResp, properties))
2474 {
2475 messages::internalError(aResp->res);
2476 return;
2477 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002478 });
George Liue99073f2022-12-09 11:06:16 +08002479 });
Chris Cain37bbf982021-09-20 10:53:09 -05002480
2481 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2482}
2483
2484/**
2485 * @brief Sets Idle Power Saver properties.
2486 *
2487 * @param[in] aResp Shared pointer for generating response message.
2488 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2489 * RF request.
2490 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2491 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2492 * before entering idle state.
2493 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2494 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2495 * before exiting idle state
2496 *
2497 * @return None.
2498 */
2499inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2500 const std::optional<bool> ipsEnable,
2501 const std::optional<uint8_t> ipsEnterUtil,
2502 const std::optional<uint64_t> ipsEnterTime,
2503 const std::optional<uint8_t> ipsExitUtil,
2504 const std::optional<uint64_t> ipsExitTime)
2505{
2506 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2507
2508 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002509 constexpr std::array<std::string_view, 1> interfaces = {
2510 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2511 dbus::utility::getSubTree(
2512 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002513 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002514 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002515 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002516 if (ec)
2517 {
2518 BMCWEB_LOG_DEBUG
2519 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2520 << ec;
2521 messages::internalError(aResp->res);
2522 return;
2523 }
2524 if (subtree.empty())
2525 {
2526 // This is an optional D-Bus object, but user attempted to patch
2527 messages::resourceNotFound(aResp->res, "ComputerSystem",
2528 "IdlePowerSaver");
2529 return;
2530 }
2531 if (subtree.size() > 1)
2532 {
2533 // More then one PowerIdlePowerSaver object is not supported and
2534 // is an error
2535 BMCWEB_LOG_DEBUG
2536 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2537 << subtree.size();
2538 messages::internalError(aResp->res);
2539 return;
2540 }
2541 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2542 {
2543 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2544 messages::internalError(aResp->res);
2545 return;
2546 }
2547 const std::string& path = subtree[0].first;
2548 const std::string& service = subtree[0].second.begin()->first;
2549 if (service.empty())
2550 {
2551 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2552 messages::internalError(aResp->res);
2553 return;
2554 }
Chris Cain37bbf982021-09-20 10:53:09 -05002555
Ed Tanous002d39b2022-05-31 08:59:27 -07002556 // Valid Power IdlePowerSaver object found, now set any values that
2557 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002558
Ed Tanous002d39b2022-05-31 08:59:27 -07002559 if (ipsEnable)
2560 {
2561 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002562 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002563 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002564 {
Ed Tanous8a592812022-06-04 09:06:59 -07002565 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002566 messages::internalError(aResp->res);
2567 return;
2568 }
2569 },
2570 service, path, "org.freedesktop.DBus.Properties", "Set",
2571 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2572 dbus::utility::DbusVariantType(*ipsEnable));
2573 }
2574 if (ipsEnterUtil)
2575 {
2576 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002577 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002578 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002579 {
Ed Tanous8a592812022-06-04 09:06:59 -07002580 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002581 messages::internalError(aResp->res);
2582 return;
2583 }
2584 },
2585 service, path, "org.freedesktop.DBus.Properties", "Set",
2586 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2587 "EnterUtilizationPercent",
2588 dbus::utility::DbusVariantType(*ipsEnterUtil));
2589 }
2590 if (ipsEnterTime)
2591 {
2592 // Convert from seconds into milliseconds for DBus
2593 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2594 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002595 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002596 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002597 {
Ed Tanous8a592812022-06-04 09:06:59 -07002598 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002599 messages::internalError(aResp->res);
2600 return;
2601 }
2602 },
2603 service, path, "org.freedesktop.DBus.Properties", "Set",
2604 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2605 "EnterDwellTime",
2606 dbus::utility::DbusVariantType(timeMilliseconds));
2607 }
2608 if (ipsExitUtil)
2609 {
2610 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002611 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002612 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002613 {
Ed Tanous8a592812022-06-04 09:06:59 -07002614 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002615 messages::internalError(aResp->res);
2616 return;
2617 }
2618 },
2619 service, path, "org.freedesktop.DBus.Properties", "Set",
2620 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2621 "ExitUtilizationPercent",
2622 dbus::utility::DbusVariantType(*ipsExitUtil));
2623 }
2624 if (ipsExitTime)
2625 {
2626 // Convert from seconds into milliseconds for DBus
2627 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2628 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002629 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002630 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002631 {
Ed Tanous8a592812022-06-04 09:06:59 -07002632 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002633 messages::internalError(aResp->res);
2634 return;
2635 }
2636 },
2637 service, path, "org.freedesktop.DBus.Properties", "Set",
2638 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2639 "ExitDwellTime",
2640 dbus::utility::DbusVariantType(timeMilliseconds));
2641 }
George Liue99073f2022-12-09 11:06:16 +08002642 });
Chris Cain37bbf982021-09-20 10:53:09 -05002643
2644 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2645}
2646
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002647inline void handleComputerSystemHead(
2648 crow::App& app, const crow::Request& req,
2649 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2650{
2651 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2652 {
2653 return;
2654 }
2655 asyncResp->res.addHeader(
2656 boost::beast::http::field::link,
2657 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2658}
2659
Yong Lic45f0082019-10-10 14:19:01 +08002660/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002661 * SystemsCollection derived class for delivering ComputerSystems Collection
2662 * Schema
2663 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002664inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002665{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002666 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002667 .privileges(redfish::privileges::headComputerSystemCollection)
2668 .methods(boost::beast::http::verb::head)(
2669 std::bind_front(handleComputerSystemHead, std::ref(app)));
2670
2671 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002672 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002673 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002674 [&app](const crow::Request& req,
2675 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002676 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002677 {
2678 return;
2679 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002680
2681 asyncResp->res.addHeader(
2682 boost::beast::http::field::link,
2683 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002684 asyncResp->res.jsonValue["@odata.type"] =
2685 "#ComputerSystemCollection.ComputerSystemCollection";
2686 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2687 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002688
Ed Tanous002d39b2022-05-31 08:59:27 -07002689 sdbusplus::asio::getProperty<std::string>(
2690 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2691 "/xyz/openbmc_project/network/hypervisor",
2692 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002693 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002694 const std::string& /*hostName*/) {
2695 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2696 ifaceArray = nlohmann::json::array();
2697 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002698
Ed Tanous002d39b2022-05-31 08:59:27 -07002699 nlohmann::json::object_t system;
2700 system["@odata.id"] = "/redfish/v1/Systems/system";
2701 ifaceArray.push_back(std::move(system));
2702 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002703 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002704 {
2705 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2706 nlohmann::json::object_t hypervisor;
2707 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2708 ifaceArray.push_back(std::move(hypervisor));
2709 count = ifaceArray.size();
2710 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002711 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002712 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002713}
Sunitha Harish462023a2020-02-19 08:34:59 -06002714
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002715/**
2716 * Function transceives data with dbus directly.
2717 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002718inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002719{
2720 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2721 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2722 constexpr char const* interfaceName =
2723 "xyz.openbmc_project.Control.Host.NMI";
2724 constexpr char const* method = "NMI";
2725
2726 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002727 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002728 if (ec)
2729 {
2730 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2731 messages::internalError(asyncResp->res);
2732 return;
2733 }
2734 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002735 },
2736 serviceName, objectPath, interfaceName, method);
2737}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002738
2739/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002740 * SystemActionsReset class supports handle POST method for Reset action.
2741 * The class retrieves and sends data directly to D-Bus.
2742 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002743inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002744{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002745 /**
2746 * Function handles POST method request.
2747 * Analyzes POST body message before sends Reset request data to D-Bus.
2748 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002749 BMCWEB_ROUTE(app,
2750 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002751 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002752 .methods(boost::beast::http::verb::post)(
2753 [&app](const crow::Request& req,
2754 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002755 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002756 {
2757 return;
2758 }
2759 std::string resetType;
2760 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2761 resetType))
2762 {
2763 return;
2764 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002765
Ed Tanous002d39b2022-05-31 08:59:27 -07002766 // Get the command and host vs. chassis
2767 std::string command;
2768 bool hostCommand = true;
2769 if ((resetType == "On") || (resetType == "ForceOn"))
2770 {
2771 command = "xyz.openbmc_project.State.Host.Transition.On";
2772 hostCommand = true;
2773 }
2774 else if (resetType == "ForceOff")
2775 {
2776 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2777 hostCommand = false;
2778 }
2779 else if (resetType == "ForceRestart")
2780 {
2781 command =
2782 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2783 hostCommand = true;
2784 }
2785 else if (resetType == "GracefulShutdown")
2786 {
2787 command = "xyz.openbmc_project.State.Host.Transition.Off";
2788 hostCommand = true;
2789 }
2790 else if (resetType == "GracefulRestart")
2791 {
2792 command =
2793 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2794 hostCommand = true;
2795 }
2796 else if (resetType == "PowerCycle")
2797 {
2798 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2799 hostCommand = true;
2800 }
2801 else if (resetType == "Nmi")
2802 {
2803 doNMI(asyncResp);
2804 return;
2805 }
2806 else
2807 {
2808 messages::actionParameterUnknown(asyncResp->res, "Reset",
2809 resetType);
2810 return;
2811 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002812
Ed Tanous002d39b2022-05-31 08:59:27 -07002813 if (hostCommand)
2814 {
2815 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002816 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002817 if (ec)
2818 {
2819 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2820 if (ec.value() == boost::asio::error::invalid_argument)
2821 {
2822 messages::actionParameterNotSupported(
2823 asyncResp->res, resetType, "Reset");
2824 }
2825 else
2826 {
2827 messages::internalError(asyncResp->res);
2828 }
2829 return;
2830 }
2831 messages::success(asyncResp->res);
2832 },
2833 "xyz.openbmc_project.State.Host",
2834 "/xyz/openbmc_project/state/host0",
2835 "org.freedesktop.DBus.Properties", "Set",
2836 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2837 dbus::utility::DbusVariantType{command});
2838 }
2839 else
2840 {
2841 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002842 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002843 if (ec)
2844 {
2845 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2846 if (ec.value() == boost::asio::error::invalid_argument)
2847 {
2848 messages::actionParameterNotSupported(
2849 asyncResp->res, resetType, "Reset");
2850 }
2851 else
2852 {
2853 messages::internalError(asyncResp->res);
2854 }
2855 return;
2856 }
2857 messages::success(asyncResp->res);
2858 },
2859 "xyz.openbmc_project.State.Chassis",
2860 "/xyz/openbmc_project/state/chassis0",
2861 "org.freedesktop.DBus.Properties", "Set",
2862 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2863 dbus::utility::DbusVariantType{command});
2864 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002865 });
2866}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002867
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002868inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002869 App& app, const crow::Request& req,
2870 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2871{
2872 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2873 {
2874 return;
2875 }
2876
2877 asyncResp->res.addHeader(
2878 boost::beast::http::field::link,
2879 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2880}
2881
Ed Tanouscc340dd2018-08-29 13:43:38 -07002882/**
Ed Tanous66173382018-08-15 18:20:59 -07002883 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002884 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002885inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002886{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002887
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002888 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2889 .privileges(redfish::privileges::headComputerSystem)
2890 .methods(boost::beast::http::verb::head)(
2891 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07002892 /**
2893 * Functions triggers appropriate requests on DBus
2894 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002895 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002896 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002897 .methods(boost::beast::http::verb::get)(
2898 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002899 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2900 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002901 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002902 {
2903 return;
2904 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002905 if (systemName != "system")
2906 {
2907 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2908 systemName);
2909 return;
2910 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002911 asyncResp->res.addHeader(
2912 boost::beast::http::field::link,
2913 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002914 asyncResp->res.jsonValue["@odata.type"] =
2915 "#ComputerSystem.v1_16_0.ComputerSystem";
2916 asyncResp->res.jsonValue["Name"] = "system";
2917 asyncResp->res.jsonValue["Id"] = "system";
2918 asyncResp->res.jsonValue["SystemType"] = "Physical";
2919 asyncResp->res.jsonValue["Description"] = "Computer System";
2920 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2921 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2922 "Disabled";
2923 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2924 uint64_t(0);
2925 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2926 "Disabled";
2927 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002928
Ed Tanous002d39b2022-05-31 08:59:27 -07002929 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
2930 "/redfish/v1/Systems/system/Processors";
2931 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
2932 "/redfish/v1/Systems/system/Memory";
2933 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
2934 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06002935 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
2936 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08002937
Ed Tanous002d39b2022-05-31 08:59:27 -07002938 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
2939 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
2940 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
2941 ["@Redfish.ActionInfo"] =
2942 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002943
Ed Tanous002d39b2022-05-31 08:59:27 -07002944 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
2945 "/redfish/v1/Systems/system/LogServices";
2946 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
2947 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002948
Ed Tanous002d39b2022-05-31 08:59:27 -07002949 nlohmann::json::array_t managedBy;
2950 nlohmann::json& manager = managedBy.emplace_back();
2951 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
2952 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
2953 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
2954 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002955
Ed Tanous002d39b2022-05-31 08:59:27 -07002956 // Fill in SerialConsole info
2957 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
2958 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
2959 true;
Ed Tanous14766872022-03-15 10:44:42 -07002960
Ed Tanous002d39b2022-05-31 08:59:27 -07002961 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2962 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
2963 true;
2964 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
2965 asyncResp->res
2966 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
2967 "Press ~. to exit console";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002968
2969#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002970 // Fill in GraphicalConsole info
2971 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
2972 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
2973 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07002974 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
2975 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07002976
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002977#endif // BMCWEB_ENABLE_KVM
George Liu7a1dbc42022-12-07 16:03:22 +08002978 constexpr std::array<std::string_view, 4> inventoryForSystems{
Ed Tanous002d39b2022-05-31 08:59:27 -07002979 "xyz.openbmc_project.Inventory.Item.Dimm",
2980 "xyz.openbmc_project.Inventory.Item.Cpu",
2981 "xyz.openbmc_project.Inventory.Item.Drive",
2982 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002983
Ed Tanous002d39b2022-05-31 08:59:27 -07002984 auto health = std::make_shared<HealthPopulate>(asyncResp);
George Liu7a1dbc42022-12-07 16:03:22 +08002985 dbus::utility::getSubTreePaths(
2986 "/", 0, inventoryForSystems,
2987 [health](const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07002988 const std::vector<std::string>& resp) {
2989 if (ec)
2990 {
2991 // no inventory
2992 return;
2993 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002994
Ed Tanous002d39b2022-05-31 08:59:27 -07002995 health->inventory = resp;
George Liu7a1dbc42022-12-07 16:03:22 +08002996 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002997
Ed Tanous002d39b2022-05-31 08:59:27 -07002998 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002999
Ed Tanous002d39b2022-05-31 08:59:27 -07003000 getMainChassisId(asyncResp,
3001 [](const std::string& chassisId,
3002 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3003 nlohmann::json::array_t chassisArray;
3004 nlohmann::json& chassis = chassisArray.emplace_back();
Willy Tueddfc432022-09-26 16:46:38 +00003005 chassis["@odata.id"] = crow::utility::urlFromPieces(
3006 "redfish", "v1", "Chassis", chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003007 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3008 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003009
Ed Tanous002d39b2022-05-31 08:59:27 -07003010 getLocationIndicatorActive(asyncResp);
3011 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3012 getIndicatorLedState(asyncResp);
3013 getComputerSystem(asyncResp, health);
3014 getHostState(asyncResp);
3015 getBootProperties(asyncResp);
3016 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003017 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003018 getPCIeDeviceList(asyncResp, "PCIeDevices");
3019 getHostWatchdogTimer(asyncResp);
3020 getPowerRestorePolicy(asyncResp);
3021 getAutomaticRetry(asyncResp);
3022 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003023#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003024 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003025#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003026 getTrustedModuleRequiredToBoot(asyncResp);
3027 getPowerMode(asyncResp);
3028 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003029 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003030
Ed Tanous22d268c2022-05-19 09:39:07 -07003031 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003032 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003033 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003034 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003035 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3036 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003037 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003038 {
3039 return;
3040 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003041 if (systemName != "system")
3042 {
3043 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3044 systemName);
3045 return;
3046 }
3047
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003048 asyncResp->res.addHeader(
3049 boost::beast::http::field::link,
3050 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3051
Ed Tanous002d39b2022-05-31 08:59:27 -07003052 std::optional<bool> locationIndicatorActive;
3053 std::optional<std::string> indicatorLed;
3054 std::optional<std::string> assetTag;
3055 std::optional<std::string> powerRestorePolicy;
3056 std::optional<std::string> powerMode;
3057 std::optional<bool> wdtEnable;
3058 std::optional<std::string> wdtTimeOutAction;
3059 std::optional<std::string> bootSource;
3060 std::optional<std::string> bootType;
3061 std::optional<std::string> bootEnable;
3062 std::optional<std::string> bootAutomaticRetry;
3063 std::optional<bool> bootTrustedModuleRequired;
3064 std::optional<bool> ipsEnable;
3065 std::optional<uint8_t> ipsEnterUtil;
3066 std::optional<uint64_t> ipsEnterTime;
3067 std::optional<uint8_t> ipsExitUtil;
3068 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003069
Ed Tanous002d39b2022-05-31 08:59:27 -07003070 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003071 if (!json_util::readJsonPatch(
3072 req, asyncResp->res,
3073 "IndicatorLED", indicatorLed,
3074 "LocationIndicatorActive", locationIndicatorActive,
3075 "AssetTag", assetTag,
3076 "PowerRestorePolicy", powerRestorePolicy,
3077 "PowerMode", powerMode,
3078 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3079 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3080 "Boot/BootSourceOverrideTarget", bootSource,
3081 "Boot/BootSourceOverrideMode", bootType,
3082 "Boot/BootSourceOverrideEnabled", bootEnable,
3083 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
3084 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3085 "IdlePowerSaver/Enabled", ipsEnable,
3086 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3087 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3088 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3089 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3090 {
3091 return;
3092 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003093 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003094
Ed Tanous002d39b2022-05-31 08:59:27 -07003095 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003096
Ed Tanous002d39b2022-05-31 08:59:27 -07003097 if (assetTag)
3098 {
3099 setAssetTag(asyncResp, *assetTag);
3100 }
James Feistb49ac872019-05-21 15:12:01 -07003101
Ed Tanous002d39b2022-05-31 08:59:27 -07003102 if (wdtEnable || wdtTimeOutAction)
3103 {
3104 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3105 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003106
Ed Tanous002d39b2022-05-31 08:59:27 -07003107 if (bootSource || bootType || bootEnable)
3108 {
3109 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3110 }
3111 if (bootAutomaticRetry)
3112 {
3113 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3114 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003115
Ed Tanous002d39b2022-05-31 08:59:27 -07003116 if (bootTrustedModuleRequired)
3117 {
3118 setTrustedModuleRequiredToBoot(asyncResp,
3119 *bootTrustedModuleRequired);
3120 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003121
Ed Tanous002d39b2022-05-31 08:59:27 -07003122 if (locationIndicatorActive)
3123 {
3124 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3125 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003126
Ed Tanous002d39b2022-05-31 08:59:27 -07003127 // TODO (Gunnar): Remove IndicatorLED after enough time has
3128 // passed
3129 if (indicatorLed)
3130 {
3131 setIndicatorLedState(asyncResp, *indicatorLed);
3132 asyncResp->res.addHeader(boost::beast::http::field::warning,
3133 "299 - \"IndicatorLED is deprecated. Use "
3134 "LocationIndicatorActive instead.\"");
3135 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003136
Ed Tanous002d39b2022-05-31 08:59:27 -07003137 if (powerRestorePolicy)
3138 {
3139 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3140 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003141
Ed Tanous002d39b2022-05-31 08:59:27 -07003142 if (powerMode)
3143 {
3144 setPowerMode(asyncResp, *powerMode);
3145 }
Chris Cain37bbf982021-09-20 10:53:09 -05003146
Ed Tanous002d39b2022-05-31 08:59:27 -07003147 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3148 ipsExitTime)
3149 {
3150 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3151 ipsExitUtil, ipsExitTime);
3152 }
3153 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003154}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303155
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003156inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003157 crow::App& app, const crow::Request& req,
3158 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3159{
3160 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3161 {
3162 return;
3163 }
3164 asyncResp->res.addHeader(
3165 boost::beast::http::field::link,
3166 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3167}
3168
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303169/**
3170 * SystemResetActionInfo derived class for delivering Computer Systems
3171 * ResetType AllowableValues using ResetInfo schema.
3172 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003173inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303174{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003175 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3176 .privileges(redfish::privileges::headActionInfo)
3177 .methods(boost::beast::http::verb::head)(std::bind_front(
3178 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303179 /**
3180 * Functions triggers appropriate requests on DBus
3181 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003182 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003183 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003184 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003185 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003186 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3187 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003188 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003189 {
3190 return;
3191 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003192 if (systemName != "system")
3193 {
3194 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3195 systemName);
3196 return;
3197 }
3198
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003199 asyncResp->res.addHeader(
3200 boost::beast::http::field::link,
3201 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003202
Ed Tanous002d39b2022-05-31 08:59:27 -07003203 asyncResp->res.jsonValue["@odata.id"] =
3204 "/redfish/v1/Systems/system/ResetActionInfo";
3205 asyncResp->res.jsonValue["@odata.type"] =
3206 "#ActionInfo.v1_1_2.ActionInfo";
3207 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3208 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003209
3210 nlohmann::json::array_t parameters;
3211 nlohmann::json::object_t parameter;
3212
3213 parameter["Name"] = "ResetType";
3214 parameter["Required"] = true;
3215 parameter["DataType"] = "String";
3216 nlohmann::json::array_t allowableValues;
3217 allowableValues.emplace_back("On");
3218 allowableValues.emplace_back("ForceOff");
3219 allowableValues.emplace_back("ForceOn");
3220 allowableValues.emplace_back("ForceRestart");
3221 allowableValues.emplace_back("GracefulRestart");
3222 allowableValues.emplace_back("GracefulShutdown");
3223 allowableValues.emplace_back("PowerCycle");
3224 allowableValues.emplace_back("Nmi");
3225 parameter["AllowableValues"] = std::move(allowableValues);
3226 parameters.emplace_back(std::move(parameter));
3227
3228 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003229 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003230}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003231} // namespace redfish