blob: 19e5e648a54418594481ffe2a303c3a66e80b493 [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"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060022#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080023#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080024#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070025#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080026#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080027#include "registries/privilege_registry.hpp"
28#include "utils/dbus_utils.hpp"
29#include "utils/json_utils.hpp"
30#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070031#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080032
Ed Tanous9712f8a2018-09-21 13:38:49 -070033#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080034#include <boost/system/error_code.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070035#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020036#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050037
George Liu7a1dbc42022-12-07 16:03:22 +080038#include <array>
39#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080040#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020041
Ed Tanous1abe55e2018-09-05 08:30:59 -070042namespace redfish
43{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020044
Abhishek Patel5c3e9272021-06-24 10:11:33 -050045const static std::array<std::pair<std::string_view, std::string_view>, 2>
46 protocolToDBusForSystems{
47 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
48
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049/**
50 * @brief Updates the Functional State of DIMMs
51 *
52 * @param[in] aResp Shared pointer for completing asynchronous calls
53 * @param[in] dimmState Dimm's Functional state, true/false
54 *
55 * @return None.
56 */
zhanghch058d1b46d2021-04-01 11:18:24 +080057inline void
58 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070059 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050060{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070061 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050062
Gunnar Mills4e0453b2020-07-08 14:00:30 -050063 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050064 // Update STATE only if previous State was DISABLED and current Dimm is
65 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070066 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050067 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
68 if (prevMemSummary == "Disabled")
69 {
Ed Tanouse05aec52022-01-25 10:28:56 -080070 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050071 {
72 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
73 "Enabled";
74 }
75 }
76}
77
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050078/*
79 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
80 *
81 * @param[in] aResp Shared pointer for completing asynchronous calls
82 * @param[in] cpuPresenceState CPU present or not
83 *
84 * @return None.
85 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070086inline void
87 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
88 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050089{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070090 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091
Ed Tanous55f79e62022-01-25 11:26:16 -080092 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050094 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080095 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080096 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050097 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080098 if (procCountPtr != nullptr)
99 {
100 // shouldn't be possible to be nullptr
101 *procCountPtr += 1;
102 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500104}
105
106/*
107 * @brief Update "ProcessorSummary" "Status" "State" based on
108 * CPU Functional State
109 *
110 * @param[in] aResp Shared pointer for completing asynchronous calls
111 * @param[in] cpuFunctionalState is CPU functional true/false
112 *
113 * @return None.
114 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700115inline void
116 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
117 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700119 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500120
Ed Tanous02cad962022-06-30 16:50:15 -0700121 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500122 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
123
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500124 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500125 // Update STATE only if previous State was Non_Functional and current CPU is
126 // Functional.
127 if (prevProcState == "Disabled")
128 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800129 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500130 {
131 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
132 "Enabled";
133 }
134 }
135}
136
Ali Ahmed382d6472021-09-03 16:53:53 -0500137inline void getProcessorProperties(
138 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
139 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
140 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500141{
Ali Ahmed03fbed92021-09-03 02:33:43 -0500142 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
143
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200144 // TODO: Get Model
145
146 const uint16_t* coreCount = nullptr;
147
148 const bool success = sdbusplus::unpackPropertiesNoThrow(
149 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
150
151 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500152 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200153 messages::internalError(aResp->res);
154 return;
155 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500156
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200157 if (coreCount != nullptr)
158 {
159 nlohmann::json& coreCountJson =
160 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
161 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500162
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200163 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500164 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200165 coreCountJson = *coreCount;
166 }
167 else
168 {
169 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500170 }
171 }
172}
173
174/*
175 * @brief Get ProcessorSummary fields
176 *
177 * @param[in] aResp Shared pointer for completing asynchronous calls
178 * @param[in] service dbus service for Cpu Information
179 * @param[in] path dbus path for Cpu
180 *
181 * @return None.
182 */
183inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
184 const std::string& service,
185 const std::string& path)
186{
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800187 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500188 const bool cpuPresenceCheck) {
189 if (ec3)
190 {
191 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
192 return;
193 }
194 modifyCpuPresenceState(aResp, cpuPresenceCheck);
195 };
196
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800197 auto getCpuFunctionalState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500198 const bool cpuFunctionalCheck) {
199 if (ec3)
200 {
201 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
202 return;
203 }
204 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
205 };
206
207 // Get the Presence of CPU
208 sdbusplus::asio::getProperty<bool>(
209 *crow::connections::systemBus, service, path,
210 "xyz.openbmc_project.Inventory.Item", "Present",
211 std::move(getCpuPresenceState));
212
213 // Get the Functional State
214 sdbusplus::asio::getProperty<bool>(
215 *crow::connections::systemBus, service, path,
216 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
217 std::move(getCpuFunctionalState));
218
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200219 sdbusplus::asio::getAllProperties(
220 *crow::connections::systemBus, service, path,
221 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500222 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800223 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800224 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700225 if (ec2)
226 {
227 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
228 messages::internalError(aResp->res);
229 return;
230 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500231 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200232 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500233}
234
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500235/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700236 * @brief Retrieves computer system properties over dbus
237 *
238 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500239 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700240 *
241 * @return None.
242 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700243inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800244 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700245 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700246{
Ed Tanous6c34de42018-08-29 13:37:36 -0700247 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800248 constexpr std::array<std::string_view, 5> interfaces = {
249 "xyz.openbmc_project.Inventory.Decorator.Asset",
250 "xyz.openbmc_project.Inventory.Item.Cpu",
251 "xyz.openbmc_project.Inventory.Item.Dimm",
252 "xyz.openbmc_project.Inventory.Item.System",
253 "xyz.openbmc_project.Common.UUID",
254 };
255 dbus::utility::getSubTree(
256 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800257 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800258 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800259 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700260 if (ec)
261 {
262 BMCWEB_LOG_DEBUG << "DBUS response error";
263 messages::internalError(aResp->res);
264 return;
265 }
266 // Iterate over all retrieved ObjectPaths.
267 for (const std::pair<
268 std::string,
269 std::vector<std::pair<std::string, std::vector<std::string>>>>&
270 object : subtree)
271 {
272 const std::string& path = object.first;
273 BMCWEB_LOG_DEBUG << "Got path: " << path;
274 const std::vector<std::pair<std::string, std::vector<std::string>>>&
275 connectionNames = object.second;
276 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700277 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700278 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700279 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700280
281 auto memoryHealth = std::make_shared<HealthPopulate>(
282 aResp, "/MemorySummary/Status"_json_pointer);
283
284 auto cpuHealth = std::make_shared<HealthPopulate>(
285 aResp, "/ProcessorSummary/Status"_json_pointer);
286
287 systemHealth->children.emplace_back(memoryHealth);
288 systemHealth->children.emplace_back(cpuHealth);
289
290 // This is not system, so check if it's cpu, dimm, UUID or
291 // BiosVer
292 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700293 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700294 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700295 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700296 if (interfaceName ==
297 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700298 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700299 BMCWEB_LOG_DEBUG
300 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500301
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200302 sdbusplus::asio::getAllProperties(
303 *crow::connections::systemBus, connection.first,
304 path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanous002d39b2022-05-31 08:59:27 -0700305 [aResp, service{connection.first},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800306 path](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700307 const dbus::utility::DBusPropertiesMap&
308 properties) {
309 if (ec2)
310 {
311 BMCWEB_LOG_ERROR << "DBUS response error "
312 << ec2;
313 messages::internalError(aResp->res);
314 return;
315 }
316 BMCWEB_LOG_DEBUG << "Got " << properties.size()
317 << " Dimm properties.";
318
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200319 if (properties.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700320 {
321 sdbusplus::asio::getProperty<bool>(
322 *crow::connections::systemBus, service,
323 path,
324 "xyz.openbmc_project.State."
325 "Decorator.OperationalStatus",
326 "Functional",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800327 [aResp](
328 const boost::system::error_code& ec3,
329 bool dimmState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700330 if (ec3)
331 {
332 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000333 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800334 return;
335 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700336 updateDimmProperties(aResp, dimmState);
337 });
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200338 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700339 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200340
341 const uint32_t* memorySizeInKB = nullptr;
342
343 const bool success =
344 sdbusplus::unpackPropertiesNoThrow(
345 dbus_utils::UnpackErrorPrinter(),
346 properties, "MemorySizeInKB",
347 memorySizeInKB);
348
349 if (!success)
350 {
351 messages::internalError(aResp->res);
352 return;
353 }
354
355 if (memorySizeInKB != nullptr)
356 {
357 nlohmann::json& totalMemory =
358 aResp->res
359 .jsonValue["MemorySummary"]
360 ["TotalSystemMemoryGiB"];
361 const uint64_t* preValue =
362 totalMemory.get_ptr<const uint64_t*>();
363 if (preValue == nullptr)
364 {
365 aResp->res
366 .jsonValue["MemorySummary"]
367 ["TotalSystemMemoryGiB"] =
368 *memorySizeInKB / (1024 * 1024);
369 }
370 else
371 {
372 aResp->res
373 .jsonValue["MemorySummary"]
374 ["TotalSystemMemoryGiB"] =
375 *memorySizeInKB / (1024 * 1024) +
376 *preValue;
377 }
378 aResp->res.jsonValue["MemorySummary"]["Status"]
379 ["State"] = "Enabled";
380 }
381 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700382
383 memoryHealth->inventory.emplace_back(path);
384 }
385 else if (interfaceName ==
386 "xyz.openbmc_project.Inventory.Item.Cpu")
387 {
388 BMCWEB_LOG_DEBUG
389 << "Found Cpu, now get its properties.";
390
391 getProcessorSummary(aResp, connection.first, path);
392
393 cpuHealth->inventory.emplace_back(path);
394 }
395 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
396 {
397 BMCWEB_LOG_DEBUG
398 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200399
400 sdbusplus::asio::getAllProperties(
401 *crow::connections::systemBus, connection.first,
402 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800403 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700404 const dbus::utility::DBusPropertiesMap&
405 properties) {
406 if (ec3)
407 {
408 BMCWEB_LOG_DEBUG << "DBUS response error "
409 << ec3;
410 messages::internalError(aResp->res);
411 return;
412 }
413 BMCWEB_LOG_DEBUG << "Got " << properties.size()
414 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700415
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200416 const std::string* uUID = nullptr;
417
418 const bool success =
419 sdbusplus::unpackPropertiesNoThrow(
420 dbus_utils::UnpackErrorPrinter(),
421 properties, "UUID", uUID);
422
423 if (!success)
424 {
425 messages::internalError(aResp->res);
426 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700427 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200428
429 if (uUID != nullptr)
430 {
431 std::string valueStr = *uUID;
432 if (valueStr.size() == 32)
433 {
434 valueStr.insert(8, 1, '-');
435 valueStr.insert(13, 1, '-');
436 valueStr.insert(18, 1, '-');
437 valueStr.insert(23, 1, '-');
438 }
439 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
440 aResp->res.jsonValue["UUID"] = valueStr;
441 }
442 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700443 }
444 else if (interfaceName ==
445 "xyz.openbmc_project.Inventory.Item.System")
446 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200447 sdbusplus::asio::getAllProperties(
448 *crow::connections::systemBus, connection.first,
449 path,
450 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800451 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700452 const dbus::utility::DBusPropertiesMap&
453 propertiesList) {
454 if (ec2)
455 {
456 // doesn't have to include this
457 // interface
458 return;
459 }
460 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
461 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200462
463 const std::string* partNumber = nullptr;
464 const std::string* serialNumber = nullptr;
465 const std::string* manufacturer = nullptr;
466 const std::string* model = nullptr;
467 const std::string* subModel = nullptr;
468
469 const bool success =
470 sdbusplus::unpackPropertiesNoThrow(
471 dbus_utils::UnpackErrorPrinter(),
472 propertiesList, "PartNumber", partNumber,
473 "SerialNumber", serialNumber,
474 "Manufacturer", manufacturer, "Model",
475 model, "SubModel", subModel);
476
477 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700478 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200479 messages::internalError(aResp->res);
480 return;
481 }
482
483 if (partNumber != nullptr)
484 {
485 aResp->res.jsonValue["PartNumber"] =
486 *partNumber;
487 }
488
489 if (serialNumber != nullptr)
490 {
491 aResp->res.jsonValue["SerialNumber"] =
492 *serialNumber;
493 }
494
495 if (manufacturer != nullptr)
496 {
497 aResp->res.jsonValue["Manufacturer"] =
498 *manufacturer;
499 }
500
501 if (model != nullptr)
502 {
503 aResp->res.jsonValue["Model"] = *model;
504 }
505
506 if (subModel != nullptr)
507 {
508 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700509 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500510
Ed Tanous002d39b2022-05-31 08:59:27 -0700511 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700512 sw_util::populateSoftwareInformation(
513 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700514 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200515 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700516
Ed Tanous002d39b2022-05-31 08:59:27 -0700517 sdbusplus::asio::getProperty<std::string>(
518 *crow::connections::systemBus, connection.first,
519 path,
520 "xyz.openbmc_project.Inventory.Decorator."
521 "AssetTag",
522 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800523 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700524 const std::string& value) {
525 if (ec2)
526 {
527 // doesn't have to include this
528 // interface
529 return;
530 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700531
Ed Tanous002d39b2022-05-31 08:59:27 -0700532 aResp->res.jsonValue["AssetTag"] = value;
533 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700534 }
535 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200536 break;
Ed Tanous6c34de42018-08-29 13:37:36 -0700537 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700538 }
Ed Tanous66173382018-08-15 18:20:59 -0700539 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700540}
541
542/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700543 * @brief Retrieves host state properties over dbus
544 *
545 * @param[in] aResp Shared pointer for completing asynchronous calls.
546 *
547 * @return None.
548 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800549inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700550{
551 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700552 sdbusplus::asio::getProperty<std::string>(
553 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
554 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
555 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800556 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700557 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700558 if (ec)
559 {
560 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700561 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700562 // Service not available, no error, just don't return
563 // host state info
564 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700565 return;
566 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700567 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
568 messages::internalError(aResp->res);
569 return;
570 }
Ed Tanous66173382018-08-15 18:20:59 -0700571
Ed Tanous002d39b2022-05-31 08:59:27 -0700572 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
573 // Verify Host State
574 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
575 {
576 aResp->res.jsonValue["PowerState"] = "On";
577 aResp->res.jsonValue["Status"]["State"] = "Enabled";
578 }
579 else if (hostState ==
580 "xyz.openbmc_project.State.Host.HostState.Quiesced")
581 {
582 aResp->res.jsonValue["PowerState"] = "On";
583 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
584 }
585 else if (hostState ==
586 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
587 {
588 aResp->res.jsonValue["PowerState"] = "On";
589 aResp->res.jsonValue["Status"]["State"] = "InTest";
590 }
591 else if (
592 hostState ==
593 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
594 {
595 aResp->res.jsonValue["PowerState"] = "PoweringOn";
596 aResp->res.jsonValue["Status"]["State"] = "Starting";
597 }
598 else if (hostState ==
599 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
600 {
601 aResp->res.jsonValue["PowerState"] = "PoweringOff";
602 aResp->res.jsonValue["Status"]["State"] = "Disabled";
603 }
604 else
605 {
606 aResp->res.jsonValue["PowerState"] = "Off";
607 aResp->res.jsonValue["Status"]["State"] = "Disabled";
608 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700609 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700610}
611
612/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500613 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530614 *
615 * @param[in] dbusSource The boot source in DBUS speak.
616 *
617 * @return Returns as a string, the boot source in Redfish terms. If translation
618 * cannot be done, returns an empty string.
619 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000620inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530621{
622 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
623 {
624 return "None";
625 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700626 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530627 {
628 return "Hdd";
629 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700630 if (dbusSource ==
631 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530632 {
633 return "Cd";
634 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700635 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530636 {
637 return "Pxe";
638 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700639 if (dbusSource ==
640 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700641 {
642 return "Usb";
643 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700644 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530645}
646
647/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300648 * @brief Translates boot type DBUS property value to redfish.
649 *
650 * @param[in] dbusType The boot type in DBUS speak.
651 *
652 * @return Returns as a string, the boot type in Redfish terms. If translation
653 * cannot be done, returns an empty string.
654 */
655inline std::string dbusToRfBootType(const std::string& dbusType)
656{
657 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
658 {
659 return "Legacy";
660 }
661 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
662 {
663 return "UEFI";
664 }
665 return "";
666}
667
668/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500669 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530670 *
671 * @param[in] dbusMode The boot mode in DBUS speak.
672 *
673 * @return Returns as a string, the boot mode in Redfish terms. If translation
674 * cannot be done, returns an empty string.
675 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000676inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530677{
678 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
679 {
680 return "None";
681 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700682 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530683 {
684 return "Diags";
685 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700686 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530687 {
688 return "BiosSetup";
689 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700690 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530691}
692
693/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600694 * @brief Translates boot progress DBUS property value to redfish.
695 *
696 * @param[in] dbusBootProgress The boot progress in DBUS speak.
697 *
698 * @return Returns as a string, the boot progress in Redfish terms. If
699 * translation cannot be done, returns "None".
700 */
701inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
702{
703 // Now convert the D-Bus BootProgress to the appropriate Redfish
704 // enum
705 std::string rfBpLastState = "None";
706 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
707 "ProgressStages.Unspecified")
708 {
709 rfBpLastState = "None";
710 }
711 else if (dbusBootProgress ==
712 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
713 "PrimaryProcInit")
714 {
715 rfBpLastState = "PrimaryProcessorInitializationStarted";
716 }
717 else if (dbusBootProgress ==
718 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
719 "BusInit")
720 {
721 rfBpLastState = "BusInitializationStarted";
722 }
723 else if (dbusBootProgress ==
724 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
725 "MemoryInit")
726 {
727 rfBpLastState = "MemoryInitializationStarted";
728 }
729 else if (dbusBootProgress ==
730 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
731 "SecondaryProcInit")
732 {
733 rfBpLastState = "SecondaryProcessorInitializationStarted";
734 }
735 else if (dbusBootProgress ==
736 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
737 "PCIInit")
738 {
739 rfBpLastState = "PCIResourceConfigStarted";
740 }
741 else if (dbusBootProgress ==
742 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
743 "SystemSetup")
744 {
745 rfBpLastState = "SetupEntered";
746 }
747 else if (dbusBootProgress ==
748 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
749 "SystemInitComplete")
750 {
751 rfBpLastState = "SystemHardwareInitializationComplete";
752 }
753 else if (dbusBootProgress ==
754 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
755 "OSStart")
756 {
757 rfBpLastState = "OSBootStarted";
758 }
759 else if (dbusBootProgress ==
760 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
761 "OSRunning")
762 {
763 rfBpLastState = "OSRunning";
764 }
765 else
766 {
767 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
768 << dbusBootProgress;
769 // Just return the default
770 }
771 return rfBpLastState;
772}
773
774/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500775 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530776 *
777 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700778 * @param[out] bootSource The DBus source
779 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700781 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530782 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800783inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500784 const std::string& rfSource,
785 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530786{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300787 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
788 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700789
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530790 if (rfSource == "None")
791 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700792 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530793 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700794 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530795 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700796 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
797 }
798 else if (rfSource == "Hdd")
799 {
800 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
801 }
802 else if (rfSource == "Diags")
803 {
804 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
805 }
806 else if (rfSource == "Cd")
807 {
808 bootSource =
809 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
810 }
811 else if (rfSource == "BiosSetup")
812 {
813 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530814 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700815 else if (rfSource == "Usb")
816 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700817 bootSource =
818 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700819 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530820 else
821 {
George Liu0fda0f12021-11-16 10:06:17 +0800822 BMCWEB_LOG_DEBUG
823 << "Invalid property value for BootSourceOverrideTarget: "
824 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700825 messages::propertyValueNotInList(aResp->res, rfSource,
826 "BootSourceTargetOverride");
827 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700829 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530830}
Ali Ahmed19817712021-06-29 17:01:52 -0500831
Andrew Geissler978b8802020-11-19 13:36:40 -0600832/**
833 * @brief Retrieves boot progress of the system
834 *
835 * @param[in] aResp Shared pointer for generating response message.
836 *
837 * @return None.
838 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800839inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600840{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700841 sdbusplus::asio::getProperty<std::string>(
842 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
843 "/xyz/openbmc_project/state/host0",
844 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800845 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700846 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700847 if (ec)
848 {
849 // BootProgress is an optional object so just do nothing if
850 // not found
851 return;
852 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600853
Ed Tanous002d39b2022-05-31 08:59:27 -0700854 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600855
Ed Tanous002d39b2022-05-31 08:59:27 -0700856 aResp->res.jsonValue["BootProgress"]["LastState"] =
857 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700858 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600859}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530860
861/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000862 * @brief Retrieves boot progress Last Update of the system
863 *
864 * @param[in] aResp Shared pointer for generating response message.
865 *
866 * @return None.
867 */
868inline void getBootProgressLastStateTime(
869 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
870{
871 sdbusplus::asio::getProperty<uint64_t>(
872 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
873 "/xyz/openbmc_project/state/host0",
874 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800875 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000876 const uint64_t lastStateTime) {
877 if (ec)
878 {
879 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
880 return;
881 }
882
883 // BootProgressLastUpdate is the last time the BootProgress property
884 // was updated. The time is the Epoch time, number of microseconds
885 // since 1 Jan 1970 00::00::00 UTC."
886 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
887 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
888
889 // Convert to ISO 8601 standard
890 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
891 redfish::time_utils::getDateTimeUintUs(lastStateTime);
892 });
893}
894
895/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300896 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300897 *
898 * @param[in] aResp Shared pointer for generating response message.
899 *
900 * @return None.
901 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300902
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300903inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300904{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700905 sdbusplus::asio::getProperty<std::string>(
906 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
907 "/xyz/openbmc_project/control/host0/boot",
908 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800909 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700910 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700911 if (ec)
912 {
913 // not an error, don't have to have the interface
914 return;
915 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300916
Ed Tanous002d39b2022-05-31 08:59:27 -0700917 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918
Ed Tanous002d39b2022-05-31 08:59:27 -0700919 aResp->res.jsonValue["Boot"]
920 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700921 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300922
Ed Tanous002d39b2022-05-31 08:59:27 -0700923 auto rfType = dbusToRfBootType(bootType);
924 if (rfType.empty())
925 {
926 messages::internalError(aResp->res);
927 return;
928 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300929
Ed Tanous002d39b2022-05-31 08:59:27 -0700930 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700931 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300932}
933
934/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300935 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530936 *
937 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938 *
939 * @return None.
940 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300941
942inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530943{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700944 sdbusplus::asio::getProperty<std::string>(
945 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
946 "/xyz/openbmc_project/control/host0/boot",
947 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800948 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700949 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700950 if (ec)
951 {
952 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
953 messages::internalError(aResp->res);
954 return;
955 }
956
957 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
958
959 aResp->res
960 .jsonValue["Boot"]
961 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
962 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
963
964 if (bootModeStr !=
965 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
966 {
967 auto rfMode = dbusToRfBootMode(bootModeStr);
968 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700970 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
971 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530972 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700973 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700974 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530975}
976
977/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300978 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530979 *
980 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530981 *
982 * @return None.
983 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300984
985inline void
986 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530987{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700988 sdbusplus::asio::getProperty<std::string>(
989 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
990 "/xyz/openbmc_project/control/host0/boot",
991 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800992 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700993 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700994 if (ec)
995 {
996 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000997 if (ec.value() == boost::asio::error::host_unreachable)
998 {
999 return;
1000 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001001 messages::internalError(aResp->res);
1002 return;
1003 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301004
Ed Tanous002d39b2022-05-31 08:59:27 -07001005 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301006
Ed Tanous002d39b2022-05-31 08:59:27 -07001007 auto rfSource = dbusToRfBootSource(bootSourceStr);
1008 if (!rfSource.empty())
1009 {
1010 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1011 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001012
Ed Tanous002d39b2022-05-31 08:59:27 -07001013 // Get BootMode as BootSourceOverrideTarget is constructed
1014 // from both BootSource and BootMode
1015 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001016 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301017}
1018
1019/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001020 * @brief This functions abstracts all the logic behind getting a
1021 * "BootSourceOverrideEnabled" property from an overall boot override enable
1022 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301023 *
1024 * @param[in] aResp Shared pointer for generating response message.
1025 *
1026 * @return None.
1027 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301028
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029inline void
1030 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1031 const bool bootOverrideEnableSetting)
1032{
1033 if (!bootOverrideEnableSetting)
1034 {
1035 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1036 return;
1037 }
1038
1039 // If boot source override is enabled, we need to check 'one_time'
1040 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001041 sdbusplus::asio::getProperty<bool>(
1042 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1043 "/xyz/openbmc_project/control/host0/boot/one_time",
1044 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001045 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001046 if (ec)
1047 {
1048 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1049 messages::internalError(aResp->res);
1050 return;
1051 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301052
Ed Tanous002d39b2022-05-31 08:59:27 -07001053 if (oneTimeSetting)
1054 {
1055 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1056 }
1057 else
1058 {
1059 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1060 "Continuous";
1061 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001062 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301063}
1064
1065/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001066 * @brief Retrieves boot override enable over DBUS
1067 *
1068 * @param[in] aResp Shared pointer for generating response message.
1069 *
1070 * @return None.
1071 */
1072
1073inline void
1074 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1075{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001076 sdbusplus::asio::getProperty<bool>(
1077 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1078 "/xyz/openbmc_project/control/host0/boot",
1079 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001080 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001081 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001082 if (ec)
1083 {
1084 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001085 if (ec.value() == boost::asio::error::host_unreachable)
1086 {
1087 return;
1088 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001089 messages::internalError(aResp->res);
1090 return;
1091 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001092
Ed Tanous002d39b2022-05-31 08:59:27 -07001093 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001094 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001095}
1096
1097/**
1098 * @brief Retrieves boot source override properties
1099 *
1100 * @param[in] aResp Shared pointer for generating response message.
1101 *
1102 * @return None.
1103 */
1104inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1105{
1106 BMCWEB_LOG_DEBUG << "Get boot information.";
1107
1108 getBootOverrideSource(aResp);
1109 getBootOverrideType(aResp);
1110 getBootOverrideEnable(aResp);
1111}
1112
1113/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001114 * @brief Retrieves the Last Reset Time
1115 *
1116 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1117 * and power off. Even though this is the "system" Redfish object look at the
1118 * chassis D-Bus interface for the LastStateChangeTime since this has the
1119 * last power operation time.
1120 *
1121 * @param[in] aResp Shared pointer for generating response message.
1122 *
1123 * @return None.
1124 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001125inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001126{
1127 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1128
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001129 sdbusplus::asio::getProperty<uint64_t>(
1130 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1131 "/xyz/openbmc_project/state/chassis0",
1132 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001133 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001134 if (ec)
1135 {
1136 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1137 return;
1138 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001139
Ed Tanous002d39b2022-05-31 08:59:27 -07001140 // LastStateChangeTime is epoch time, in milliseconds
1141 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1142 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001143
Ed Tanous002d39b2022-05-31 08:59:27 -07001144 // Convert to ISO 8601 standard
1145 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001146 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001147 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001148}
1149
1150/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001151 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1152 *
1153 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1154 * corresponding property "AttemptsLeft" that keeps track of the amount of
1155 * automatic retry attempts left are hosted in phosphor-state-manager through
1156 * dbus.
1157 *
1158 * @param[in] aResp Shared pointer for generating response message.
1159 *
1160 * @return None.
1161 */
1162inline void
1163 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1164{
1165 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1166
1167 sdbusplus::asio::getAllProperties(
1168 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1169 "/xyz/openbmc_project/state/host0",
1170 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1171 [aResp{aResp}](const boost::system::error_code& ec,
1172 const dbus::utility::DBusPropertiesMap& propertiesList) {
1173 if (ec)
1174 {
1175 if (ec.value() != EBADR)
1176 {
1177 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1178 messages::internalError(aResp->res);
1179 }
1180 return;
1181 }
1182
1183 const uint32_t* attemptsLeft = nullptr;
1184 const uint32_t* retryAttempts = nullptr;
1185
1186 const bool success = sdbusplus::unpackPropertiesNoThrow(
1187 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1188 attemptsLeft, "RetryAttempts", retryAttempts);
1189
1190 if (!success)
1191 {
1192 messages::internalError(aResp->res);
1193 return;
1194 }
1195
1196 if (attemptsLeft != nullptr)
1197 {
1198 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1199 *attemptsLeft;
1200 }
1201
1202 if (retryAttempts != nullptr)
1203 {
1204 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1205 *retryAttempts;
1206 }
1207 });
1208}
1209
1210/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001211 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1212 *
1213 * @param[in] aResp Shared pointer for generating response message.
1214 *
1215 * @return None.
1216 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001217inline void
1218 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001219{
1220 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1221
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001222 sdbusplus::asio::getProperty<bool>(
1223 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1224 "/xyz/openbmc_project/control/host0/auto_reboot",
1225 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001226 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001227 if (ec)
1228 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001229 if (ec.value() != EBADR)
1230 {
1231 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1232 messages::internalError(aResp->res);
1233 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001234 return;
1235 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001236
Ed Tanous002d39b2022-05-31 08:59:27 -07001237 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1238 if (autoRebootEnabled)
1239 {
1240 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1241 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001242 }
1243 else
1244 {
1245 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1246 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001247 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001248
Ed Tanous002d39b2022-05-31 08:59:27 -07001249 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1250 // and RetryAttempts. OpenBMC only supports Disabled and
1251 // RetryAttempts.
1252 aResp->res.jsonValue["Boot"]
1253 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1254 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001255 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001256}
1257
1258/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001259 * @brief Sets RetryAttempts
1260 *
1261 * @param[in] aResp Shared pointer for generating response message.
1262 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1263 *
1264 *@return None.
1265 */
1266
1267inline void
1268 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1269 const uint32_t retryAttempts)
1270{
1271 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1272 crow::connections::systemBus->async_method_call(
1273 [aResp](const boost::system::error_code& ec) {
1274 if (ec)
1275 {
1276 BMCWEB_LOG_ERROR
1277 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1278 messages::internalError(aResp->res);
1279 return;
1280 }
1281 },
1282 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1283 "org.freedesktop.DBus.Properties", "Set",
1284 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1285 std::variant<uint32_t>(retryAttempts));
1286}
1287
1288/**
George Liuc6a620f2020-04-10 17:18:11 +08001289 * @brief Retrieves power restore policy over DBUS.
1290 *
1291 * @param[in] aResp Shared pointer for generating response message.
1292 *
1293 * @return None.
1294 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001295inline void
1296 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001297{
1298 BMCWEB_LOG_DEBUG << "Get power restore policy";
1299
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001300 sdbusplus::asio::getProperty<std::string>(
1301 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1302 "/xyz/openbmc_project/control/host0/power_restore_policy",
1303 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001304 [aResp](const boost::system::error_code& ec,
1305 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001306 if (ec)
1307 {
1308 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1309 return;
1310 }
George Liuc6a620f2020-04-10 17:18:11 +08001311
Ed Tanous002d39b2022-05-31 08:59:27 -07001312 const boost::container::flat_map<std::string, std::string> policyMaps = {
1313 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1314 "AlwaysOn"},
1315 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1316 "AlwaysOff"},
1317 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1318 "LastState"},
1319 // Return `AlwaysOff` when power restore policy set to "None"
1320 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1321 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001322
Ed Tanous002d39b2022-05-31 08:59:27 -07001323 auto policyMapsIt = policyMaps.find(policy);
1324 if (policyMapsIt == policyMaps.end())
1325 {
1326 messages::internalError(aResp->res);
1327 return;
1328 }
George Liuc6a620f2020-04-10 17:18:11 +08001329
Ed Tanous002d39b2022-05-31 08:59:27 -07001330 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001331 });
George Liuc6a620f2020-04-10 17:18:11 +08001332}
1333
1334/**
Ali Ahmed19817712021-06-29 17:01:52 -05001335 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1336 * TPM is required for booting the host.
1337 *
1338 * @param[in] aResp Shared pointer for generating response message.
1339 *
1340 * @return None.
1341 */
1342inline void getTrustedModuleRequiredToBoot(
1343 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1344{
1345 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001346 constexpr std::array<std::string_view, 1> interfaces = {
1347 "xyz.openbmc_project.Control.TPM.Policy"};
1348 dbus::utility::getSubTree(
1349 "/", 0, interfaces,
1350 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001351 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001352 if (ec)
1353 {
1354 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1355 << ec;
1356 // This is an optional D-Bus object so just return if
1357 // error occurs
1358 return;
1359 }
1360 if (subtree.empty())
1361 {
1362 // As noted above, this is an optional interface so just return
1363 // if there is no instance found
1364 return;
1365 }
1366
1367 /* When there is more than one TPMEnable object... */
1368 if (subtree.size() > 1)
1369 {
1370 BMCWEB_LOG_DEBUG
1371 << "DBUS response has more than 1 TPM Enable object:"
1372 << subtree.size();
1373 // Throw an internal Error and return
1374 messages::internalError(aResp->res);
1375 return;
1376 }
1377
1378 // Make sure the Dbus response map has a service and objectPath
1379 // field
1380 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1381 {
1382 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1383 messages::internalError(aResp->res);
1384 return;
1385 }
1386
1387 const std::string& path = subtree[0].first;
1388 const std::string& serv = subtree[0].second.begin()->first;
1389
1390 // Valid TPM Enable object found, now reading the current value
1391 sdbusplus::asio::getProperty<bool>(
1392 *crow::connections::systemBus, serv, path,
1393 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001394 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001395 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001396 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001397 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001398 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001399 messages::internalError(aResp->res);
1400 return;
1401 }
1402
Ed Tanous002d39b2022-05-31 08:59:27 -07001403 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001404 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001405 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1406 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001407 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001408 else
1409 {
1410 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1411 "Disabled";
1412 }
1413 });
George Liue99073f2022-12-09 11:06:16 +08001414 });
Ali Ahmed19817712021-06-29 17:01:52 -05001415}
1416
1417/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001418 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1419 * TPM is required for booting the host.
1420 *
1421 * @param[in] aResp Shared pointer for generating response message.
1422 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1423 *
1424 * @return None.
1425 */
1426inline void setTrustedModuleRequiredToBoot(
1427 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1428{
1429 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001430 constexpr std::array<std::string_view, 1> interfaces = {
1431 "xyz.openbmc_project.Control.TPM.Policy"};
1432 dbus::utility::getSubTree(
1433 "/", 0, interfaces,
1434 [aResp,
1435 tpmRequired](const boost::system::error_code& ec,
1436 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001437 if (ec)
1438 {
1439 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1440 << ec;
1441 messages::internalError(aResp->res);
1442 return;
1443 }
1444 if (subtree.empty())
1445 {
1446 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1447 "TrustedModuleRequiredToBoot");
1448 return;
1449 }
1450
1451 /* When there is more than one TPMEnable object... */
1452 if (subtree.size() > 1)
1453 {
1454 BMCWEB_LOG_DEBUG
1455 << "DBUS response has more than 1 TPM Enable object:"
1456 << subtree.size();
1457 // Throw an internal Error and return
1458 messages::internalError(aResp->res);
1459 return;
1460 }
1461
1462 // Make sure the Dbus response map has a service and objectPath
1463 // field
1464 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1465 {
1466 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1467 messages::internalError(aResp->res);
1468 return;
1469 }
1470
1471 const std::string& path = subtree[0].first;
1472 const std::string& serv = subtree[0].second.begin()->first;
1473
1474 if (serv.empty())
1475 {
1476 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1477 messages::internalError(aResp->res);
1478 return;
1479 }
1480
1481 // Valid TPM Enable object found, now setting the value
1482 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001483 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001484 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001485 {
1486 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001487 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001488 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001489 messages::internalError(aResp->res);
1490 return;
1491 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001492 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1493 },
1494 serv, path, "org.freedesktop.DBus.Properties", "Set",
1495 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1496 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001497 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001498}
1499
1500/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301501 * @brief Sets boot properties into DBUS object(s).
1502 *
1503 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001504 * @param[in] bootType The boot type to set.
1505 * @return Integer error code.
1506 */
1507inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001508 const std::optional<std::string>& bootType)
1509{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001510 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001511
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001512 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001513 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001514 return;
1515 }
1516
1517 // Source target specified
1518 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1519 // Figure out which DBUS interface and property to use
1520 if (*bootType == "Legacy")
1521 {
1522 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1523 }
1524 else if (*bootType == "UEFI")
1525 {
1526 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1527 }
1528 else
1529 {
1530 BMCWEB_LOG_DEBUG << "Invalid property value for "
1531 "BootSourceOverrideMode: "
1532 << *bootType;
1533 messages::propertyValueNotInList(aResp->res, *bootType,
1534 "BootSourceOverrideMode");
1535 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001536 }
1537
1538 // Act on validated parameters
1539 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1540
1541 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001542 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001543 if (ec)
1544 {
1545 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1546 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001547 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001548 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001549 return;
1550 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001551 messages::internalError(aResp->res);
1552 return;
1553 }
1554 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001555 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001556 "xyz.openbmc_project.Settings",
1557 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001558 "org.freedesktop.DBus.Properties", "Set",
1559 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001560 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001561}
1562
1563/**
1564 * @brief Sets boot properties into DBUS object(s).
1565 *
1566 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001567 * @param[in] bootType The boot type to set.
1568 * @return Integer error code.
1569 */
1570inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1571 const std::optional<std::string>& bootEnable)
1572{
1573 if (!bootEnable)
1574 {
1575 return;
1576 }
1577 // Source target specified
1578 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1579
1580 bool bootOverrideEnable = false;
1581 bool bootOverridePersistent = false;
1582 // Figure out which DBUS interface and property to use
1583 if (*bootEnable == "Disabled")
1584 {
1585 bootOverrideEnable = false;
1586 }
1587 else if (*bootEnable == "Once")
1588 {
1589 bootOverrideEnable = true;
1590 bootOverridePersistent = false;
1591 }
1592 else if (*bootEnable == "Continuous")
1593 {
1594 bootOverrideEnable = true;
1595 bootOverridePersistent = true;
1596 }
1597 else
1598 {
George Liu0fda0f12021-11-16 10:06:17 +08001599 BMCWEB_LOG_DEBUG
1600 << "Invalid property value for BootSourceOverrideEnabled: "
1601 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001602 messages::propertyValueNotInList(aResp->res, *bootEnable,
1603 "BootSourceOverrideEnabled");
1604 return;
1605 }
1606
1607 // Act on validated parameters
1608 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1609
1610 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001611 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001612 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001613 {
Ed Tanous8a592812022-06-04 09:06:59 -07001614 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001615 messages::internalError(aResp->res);
1616 return;
1617 }
1618 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001619 },
1620 "xyz.openbmc_project.Settings",
1621 "/xyz/openbmc_project/control/host0/boot",
1622 "org.freedesktop.DBus.Properties", "Set",
1623 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001624 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001625
1626 if (!bootOverrideEnable)
1627 {
1628 return;
1629 }
1630
1631 // In case boot override is enabled we need to set correct value for the
1632 // 'one_time' enable DBus interface
1633 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1634 << bootOverridePersistent;
1635
1636 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001637 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001638 if (ec)
1639 {
1640 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1641 messages::internalError(aResp->res);
1642 return;
1643 }
1644 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001645 },
1646 "xyz.openbmc_project.Settings",
1647 "/xyz/openbmc_project/control/host0/boot/one_time",
1648 "org.freedesktop.DBus.Properties", "Set",
1649 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001650 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001651}
1652
1653/**
1654 * @brief Sets boot properties into DBUS object(s).
1655 *
1656 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301657 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301658 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001659 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301660 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001661inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001662 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301663{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001664 std::string bootSourceStr;
1665 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001666
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001667 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301668 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001669 return;
1670 }
1671
1672 // Source target specified
1673 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1674 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001675 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1676 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001677 {
1678 BMCWEB_LOG_DEBUG
1679 << "Invalid property value for BootSourceOverrideTarget: "
1680 << *bootSource;
1681 messages::propertyValueNotInList(aResp->res, *bootSource,
1682 "BootSourceTargetOverride");
1683 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001684 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301685
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001686 // Act on validated parameters
1687 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1688 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001689
1690 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001691 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001692 if (ec)
1693 {
1694 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1695 messages::internalError(aResp->res);
1696 return;
1697 }
1698 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001699 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001700 "xyz.openbmc_project.Settings",
1701 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001702 "org.freedesktop.DBus.Properties", "Set",
1703 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001704 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001705
1706 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001707 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001708 if (ec)
1709 {
1710 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1711 messages::internalError(aResp->res);
1712 return;
1713 }
1714 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001715 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001716 "xyz.openbmc_project.Settings",
1717 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001718 "org.freedesktop.DBus.Properties", "Set",
1719 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001720 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001721}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001722
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001723/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001724 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301725 *
1726 * @param[in] aResp Shared pointer for generating response message.
1727 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001728 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301729 * @param[in] bootEnable The boot override enable from incoming RF request.
1730 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001731 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001733
1734inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1735 const std::optional<std::string>& bootSource,
1736 const std::optional<std::string>& bootType,
1737 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301738{
1739 BMCWEB_LOG_DEBUG << "Set boot information.";
1740
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001741 setBootModeOrSource(aResp, bootSource);
1742 setBootType(aResp, bootType);
1743 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301744}
1745
George Liuc6a620f2020-04-10 17:18:11 +08001746/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001747 * @brief Sets AssetTag
1748 *
1749 * @param[in] aResp Shared pointer for generating response message.
1750 * @param[in] assetTag "AssetTag" from request.
1751 *
1752 * @return None.
1753 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001754inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001755 const std::string& assetTag)
1756{
George Liue99073f2022-12-09 11:06:16 +08001757 constexpr std::array<std::string_view, 1> interfaces = {
1758 "xyz.openbmc_project.Inventory.Item.System"};
1759 dbus::utility::getSubTree(
1760 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001761 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001762 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001763 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001764 if (ec)
1765 {
1766 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1767 messages::internalError(aResp->res);
1768 return;
1769 }
1770 if (subtree.empty())
1771 {
1772 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1773 messages::internalError(aResp->res);
1774 return;
1775 }
1776 // Assume only 1 system D-Bus object
1777 // Throw an error if there is more than 1
1778 if (subtree.size() > 1)
1779 {
1780 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1781 messages::internalError(aResp->res);
1782 return;
1783 }
1784 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1785 {
1786 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1787 messages::internalError(aResp->res);
1788 return;
1789 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001790
Ed Tanous002d39b2022-05-31 08:59:27 -07001791 const std::string& path = subtree[0].first;
1792 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001793
Ed Tanous002d39b2022-05-31 08:59:27 -07001794 if (service.empty())
1795 {
1796 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1797 messages::internalError(aResp->res);
1798 return;
1799 }
1800
1801 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001802 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001803 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001804 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001805 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1806 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001807 messages::internalError(aResp->res);
1808 return;
1809 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001810 },
1811 service, path, "org.freedesktop.DBus.Properties", "Set",
1812 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1813 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001814 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001815}
1816
1817/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001818 * @brief Sets automaticRetry (Auto Reboot)
1819 *
1820 * @param[in] aResp Shared pointer for generating response message.
1821 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1822 *
1823 * @return None.
1824 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001825inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001826 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001827{
1828 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1829
1830 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001831 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001832
1833 if (automaticRetryConfig == "Disabled")
1834 {
1835 autoRebootEnabled = false;
1836 }
1837 else if (automaticRetryConfig == "RetryAttempts")
1838 {
1839 autoRebootEnabled = true;
1840 }
1841 else
1842 {
George Liu0fda0f12021-11-16 10:06:17 +08001843 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001844 << automaticRetryConfig;
1845 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1846 "AutomaticRetryConfig");
1847 return;
1848 }
1849
1850 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001851 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001852 if (ec)
1853 {
1854 messages::internalError(aResp->res);
1855 return;
1856 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001857 },
1858 "xyz.openbmc_project.Settings",
1859 "/xyz/openbmc_project/control/host0/auto_reboot",
1860 "org.freedesktop.DBus.Properties", "Set",
1861 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001862 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001863}
1864
1865/**
George Liuc6a620f2020-04-10 17:18:11 +08001866 * @brief Sets power restore policy properties.
1867 *
1868 * @param[in] aResp Shared pointer for generating response message.
1869 * @param[in] policy power restore policy properties from request.
1870 *
1871 * @return None.
1872 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001873inline void
1874 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1875 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001876{
1877 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1878
1879 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001880 {"AlwaysOn",
1881 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1882 {"AlwaysOff",
1883 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1884 {"LastState",
1885 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001886
1887 std::string powerRestorPolicy;
1888
Gunnar Mills4e69c902021-01-05 19:50:11 -06001889 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001890 if (policyMapsIt == policyMaps.end())
1891 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001892 messages::propertyValueNotInList(aResp->res, policy,
1893 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001894 return;
1895 }
1896
1897 powerRestorPolicy = policyMapsIt->second;
1898
1899 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001900 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001901 if (ec)
1902 {
1903 messages::internalError(aResp->res);
1904 return;
1905 }
George Liuc6a620f2020-04-10 17:18:11 +08001906 },
1907 "xyz.openbmc_project.Settings",
1908 "/xyz/openbmc_project/control/host0/power_restore_policy",
1909 "org.freedesktop.DBus.Properties", "Set",
1910 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001911 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001912}
1913
AppaRao Pulia6349912019-10-18 17:16:08 +05301914#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1915/**
1916 * @brief Retrieves provisioning status
1917 *
1918 * @param[in] aResp Shared pointer for completing asynchronous calls.
1919 *
1920 * @return None.
1921 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001922inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301923{
1924 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001925 sdbusplus::asio::getAllProperties(
1926 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1927 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001928 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001929 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001930 nlohmann::json& oemPFR =
1931 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1932 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1933 "#OemComputerSystem.OpenBmc";
1934 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001935
Ed Tanous002d39b2022-05-31 08:59:27 -07001936 if (ec)
1937 {
1938 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1939 // not an error, don't have to have the interface
1940 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1941 return;
1942 }
1943
1944 const bool* provState = nullptr;
1945 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001946
1947 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001948 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1949 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001950
1951 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001952 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001953 messages::internalError(aResp->res);
1954 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001955 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301956
Ed Tanous002d39b2022-05-31 08:59:27 -07001957 if ((provState == nullptr) || (lockState == nullptr))
1958 {
1959 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1960 messages::internalError(aResp->res);
1961 return;
1962 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301963
Ed Tanous002d39b2022-05-31 08:59:27 -07001964 if (*provState == true)
1965 {
1966 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301967 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001968 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301969 }
1970 else
1971 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001972 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301973 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001974 }
1975 else
1976 {
1977 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1978 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001979 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301980}
1981#endif
1982
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301983/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001984 * @brief Translate the PowerMode to a response message.
1985 *
1986 * @param[in] aResp Shared pointer for generating response message.
1987 * @param[in] modeValue PowerMode value to be translated
1988 *
1989 * @return None.
1990 */
1991inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1992 const std::string& modeValue)
1993{
George Liu0fda0f12021-11-16 10:06:17 +08001994 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001995 {
1996 aResp->res.jsonValue["PowerMode"] = "Static";
1997 }
George Liu0fda0f12021-11-16 10:06:17 +08001998 else if (
1999 modeValue ==
2000 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002001 {
2002 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2003 }
George Liu0fda0f12021-11-16 10:06:17 +08002004 else if (modeValue ==
2005 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002006 {
2007 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2008 }
George Liu0fda0f12021-11-16 10:06:17 +08002009 else if (modeValue ==
2010 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002011 {
2012 aResp->res.jsonValue["PowerMode"] = "OEM";
2013 }
2014 else
2015 {
2016 // Any other values would be invalid
2017 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2018 messages::internalError(aResp->res);
2019 }
2020}
2021
2022/**
2023 * @brief Retrieves system power mode
2024 *
2025 * @param[in] aResp Shared pointer for generating response message.
2026 *
2027 * @return None.
2028 */
2029inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2030{
2031 BMCWEB_LOG_DEBUG << "Get power mode.";
2032
2033 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002034 constexpr std::array<std::string_view, 1> interfaces = {
2035 "xyz.openbmc_project.Control.Power.Mode"};
2036 dbus::utility::getSubTree(
2037 "/", 0, interfaces,
2038 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002039 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002040 if (ec)
2041 {
2042 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2043 << ec;
2044 // This is an optional D-Bus object so just return if
2045 // error occurs
2046 return;
2047 }
2048 if (subtree.empty())
2049 {
2050 // As noted above, this is an optional interface so just return
2051 // if there is no instance found
2052 return;
2053 }
2054 if (subtree.size() > 1)
2055 {
2056 // More then one PowerMode object is not supported and is an
2057 // error
2058 BMCWEB_LOG_DEBUG
2059 << "Found more than 1 system D-Bus Power.Mode objects: "
2060 << subtree.size();
2061 messages::internalError(aResp->res);
2062 return;
2063 }
2064 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2065 {
2066 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2067 messages::internalError(aResp->res);
2068 return;
2069 }
2070 const std::string& path = subtree[0].first;
2071 const std::string& service = subtree[0].second.begin()->first;
2072 if (service.empty())
2073 {
2074 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2075 messages::internalError(aResp->res);
2076 return;
2077 }
2078 // Valid Power Mode object found, now read the current value
2079 sdbusplus::asio::getProperty<std::string>(
2080 *crow::connections::systemBus, service, path,
2081 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002082 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002083 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002084 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002085 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002086 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002087 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002088 messages::internalError(aResp->res);
2089 return;
2090 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002091
Ed Tanous002d39b2022-05-31 08:59:27 -07002092 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2093 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002094
Ed Tanous002d39b2022-05-31 08:59:27 -07002095 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2096 translatePowerMode(aResp, pmode);
2097 });
George Liue99073f2022-12-09 11:06:16 +08002098 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002099}
2100
2101/**
2102 * @brief Validate the specified mode is valid and return the PowerMode
2103 * name associated with that string
2104 *
2105 * @param[in] aResp Shared pointer for generating response message.
2106 * @param[in] modeString String representing the desired PowerMode
2107 *
2108 * @return PowerMode value or empty string if mode is not valid
2109 */
2110inline std::string
2111 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2112 const std::string& modeString)
2113{
2114 std::string mode;
2115
2116 if (modeString == "Static")
2117 {
2118 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2119 }
2120 else if (modeString == "MaximumPerformance")
2121 {
George Liu0fda0f12021-11-16 10:06:17 +08002122 mode =
2123 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002124 }
2125 else if (modeString == "PowerSaving")
2126 {
2127 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2128 }
2129 else
2130 {
2131 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2132 }
2133 return mode;
2134}
2135
2136/**
2137 * @brief Sets system power mode.
2138 *
2139 * @param[in] aResp Shared pointer for generating response message.
2140 * @param[in] pmode System power mode from request.
2141 *
2142 * @return None.
2143 */
2144inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2145 const std::string& pmode)
2146{
2147 BMCWEB_LOG_DEBUG << "Set power mode.";
2148
2149 std::string powerMode = validatePowerMode(aResp, pmode);
2150 if (powerMode.empty())
2151 {
2152 return;
2153 }
2154
2155 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002156 constexpr std::array<std::string_view, 1> interfaces = {
2157 "xyz.openbmc_project.Control.Power.Mode"};
2158 dbus::utility::getSubTree(
2159 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002160 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002161 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002162 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002163 if (ec)
2164 {
2165 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2166 << ec;
2167 // This is an optional D-Bus object, but user attempted to patch
2168 messages::internalError(aResp->res);
2169 return;
2170 }
2171 if (subtree.empty())
2172 {
2173 // This is an optional D-Bus object, but user attempted to patch
2174 messages::resourceNotFound(aResp->res, "ComputerSystem",
2175 "PowerMode");
2176 return;
2177 }
2178 if (subtree.size() > 1)
2179 {
2180 // More then one PowerMode object is not supported and is an
2181 // error
2182 BMCWEB_LOG_DEBUG
2183 << "Found more than 1 system D-Bus Power.Mode objects: "
2184 << subtree.size();
2185 messages::internalError(aResp->res);
2186 return;
2187 }
2188 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2189 {
2190 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2191 messages::internalError(aResp->res);
2192 return;
2193 }
2194 const std::string& path = subtree[0].first;
2195 const std::string& service = subtree[0].second.begin()->first;
2196 if (service.empty())
2197 {
2198 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2199 messages::internalError(aResp->res);
2200 return;
2201 }
2202
2203 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2204 << path;
2205
2206 // Set the Power Mode property
2207 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002208 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002209 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002210 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002211 messages::internalError(aResp->res);
2212 return;
2213 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002214 },
2215 service, path, "org.freedesktop.DBus.Properties", "Set",
2216 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2217 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002218 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002219}
2220
2221/**
Yong Li51709ff2019-09-30 14:13:04 +08002222 * @brief Translates watchdog timeout action DBUS property value to redfish.
2223 *
2224 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2225 *
2226 * @return Returns as a string, the timeout action in Redfish terms. If
2227 * translation cannot be done, returns an empty string.
2228 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002229inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002230{
2231 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2232 {
2233 return "None";
2234 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002235 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002236 {
2237 return "ResetSystem";
2238 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002239 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002240 {
2241 return "PowerDown";
2242 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002243 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002244 {
2245 return "PowerCycle";
2246 }
2247
2248 return "";
2249}
2250
2251/**
Yong Lic45f0082019-10-10 14:19:01 +08002252 *@brief Translates timeout action from Redfish to DBUS property value.
2253 *
2254 *@param[in] rfAction The timeout action in Redfish.
2255 *
2256 *@return Returns as a string, the time_out action as expected by DBUS.
2257 *If translation cannot be done, returns an empty string.
2258 */
2259
Ed Tanous23a21a12020-07-25 04:45:05 +00002260inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002261{
2262 if (rfAction == "None")
2263 {
2264 return "xyz.openbmc_project.State.Watchdog.Action.None";
2265 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002266 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002267 {
2268 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2269 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002270 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002271 {
2272 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2273 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002274 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002275 {
2276 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2277 }
2278
2279 return "";
2280}
2281
2282/**
Yong Li51709ff2019-09-30 14:13:04 +08002283 * @brief Retrieves host watchdog timer properties over DBUS
2284 *
2285 * @param[in] aResp Shared pointer for completing asynchronous calls.
2286 *
2287 * @return None.
2288 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002289inline void
2290 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002291{
2292 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002293 sdbusplus::asio::getAllProperties(
2294 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2295 "/xyz/openbmc_project/watchdog/host0",
2296 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002297 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002298 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002299 if (ec)
2300 {
2301 // watchdog service is stopped
2302 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2303 return;
2304 }
2305
2306 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2307
2308 nlohmann::json& hostWatchdogTimer =
2309 aResp->res.jsonValue["HostWatchdogTimer"];
2310
2311 // watchdog service is running/enabled
2312 hostWatchdogTimer["Status"]["State"] = "Enabled";
2313
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002314 const bool* enabled = nullptr;
2315 const std::string* expireAction = nullptr;
2316
2317 const bool success = sdbusplus::unpackPropertiesNoThrow(
2318 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2319 "ExpireAction", expireAction);
2320
2321 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002322 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002323 messages::internalError(aResp->res);
2324 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002325 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002326
2327 if (enabled != nullptr)
2328 {
2329 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2330 }
2331
2332 if (expireAction != nullptr)
2333 {
2334 std::string action = dbusToRfWatchdogAction(*expireAction);
2335 if (action.empty())
2336 {
2337 messages::internalError(aResp->res);
2338 return;
2339 }
2340 hostWatchdogTimer["TimeoutAction"] = action;
2341 }
2342 });
Yong Li51709ff2019-09-30 14:13:04 +08002343}
2344
2345/**
Yong Lic45f0082019-10-10 14:19:01 +08002346 * @brief Sets Host WatchDog Timer properties.
2347 *
2348 * @param[in] aResp Shared pointer for generating response message.
2349 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2350 * RF request.
2351 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2352 *
2353 * @return None.
2354 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002355inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002356 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002357 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002358{
2359 BMCWEB_LOG_DEBUG << "Set host watchdog";
2360
2361 if (wdtTimeOutAction)
2362 {
2363 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2364 // check if TimeOut Action is Valid
2365 if (wdtTimeOutActStr.empty())
2366 {
2367 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2368 << *wdtTimeOutAction;
2369 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2370 "TimeoutAction");
2371 return;
2372 }
2373
2374 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002375 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002376 if (ec)
2377 {
2378 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2379 messages::internalError(aResp->res);
2380 return;
2381 }
Yong Lic45f0082019-10-10 14:19:01 +08002382 },
2383 "xyz.openbmc_project.Watchdog",
2384 "/xyz/openbmc_project/watchdog/host0",
2385 "org.freedesktop.DBus.Properties", "Set",
2386 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002387 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002388 }
2389
2390 if (wdtEnable)
2391 {
2392 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002393 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002394 if (ec)
2395 {
2396 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2397 messages::internalError(aResp->res);
2398 return;
2399 }
Yong Lic45f0082019-10-10 14:19:01 +08002400 },
2401 "xyz.openbmc_project.Watchdog",
2402 "/xyz/openbmc_project/watchdog/host0",
2403 "org.freedesktop.DBus.Properties", "Set",
2404 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002405 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002406 }
2407}
2408
Chris Cain37bbf982021-09-20 10:53:09 -05002409/**
2410 * @brief Parse the Idle Power Saver properties into json
2411 *
2412 * @param[in] aResp Shared pointer for completing asynchronous calls.
2413 * @param[in] properties IPS property data from DBus.
2414 *
2415 * @return true if successful
2416 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002417inline bool
2418 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2419 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002420{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002421 const bool* enabled = nullptr;
2422 const uint8_t* enterUtilizationPercent = nullptr;
2423 const uint64_t* enterDwellTime = nullptr;
2424 const uint8_t* exitUtilizationPercent = nullptr;
2425 const uint64_t* exitDwellTime = nullptr;
2426
2427 const bool success = sdbusplus::unpackPropertiesNoThrow(
2428 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002429 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2430 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2431 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002432
2433 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002434 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002435 return false;
2436 }
2437
2438 if (enabled != nullptr)
2439 {
2440 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2441 }
2442
2443 if (enterUtilizationPercent != nullptr)
2444 {
2445 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2446 *enterUtilizationPercent;
2447 }
2448
2449 if (enterDwellTime != nullptr)
2450 {
2451 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2452 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2453 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2454 .count();
2455 }
2456
2457 if (exitUtilizationPercent != nullptr)
2458 {
2459 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2460 *exitUtilizationPercent;
2461 }
2462
2463 if (exitDwellTime != nullptr)
2464 {
2465 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2466 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2467 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2468 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002469 }
2470
2471 return true;
2472}
2473
2474/**
2475 * @brief Retrieves host watchdog timer properties over DBUS
2476 *
2477 * @param[in] aResp Shared pointer for completing asynchronous calls.
2478 *
2479 * @return None.
2480 */
2481inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2482{
2483 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2484
2485 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002486 constexpr std::array<std::string_view, 1> interfaces = {
2487 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2488 dbus::utility::getSubTree(
2489 "/", 0, interfaces,
2490 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002491 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002492 if (ec)
2493 {
2494 BMCWEB_LOG_DEBUG
2495 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2496 << ec;
2497 messages::internalError(aResp->res);
2498 return;
2499 }
2500 if (subtree.empty())
2501 {
2502 // This is an optional interface so just return
2503 // if there is no instance found
2504 BMCWEB_LOG_DEBUG << "No instances found";
2505 return;
2506 }
2507 if (subtree.size() > 1)
2508 {
2509 // More then one PowerIdlePowerSaver object is not supported and
2510 // is an error
2511 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2512 "Power.IdlePowerSaver objects: "
2513 << subtree.size();
2514 messages::internalError(aResp->res);
2515 return;
2516 }
2517 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2518 {
2519 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2520 messages::internalError(aResp->res);
2521 return;
2522 }
2523 const std::string& path = subtree[0].first;
2524 const std::string& service = subtree[0].second.begin()->first;
2525 if (service.empty())
2526 {
2527 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2528 messages::internalError(aResp->res);
2529 return;
2530 }
2531
2532 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002533 sdbusplus::asio::getAllProperties(
2534 *crow::connections::systemBus, service, path,
2535 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002536 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002537 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002538 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002539 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002540 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002541 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002542 messages::internalError(aResp->res);
2543 return;
2544 }
2545
Ed Tanous002d39b2022-05-31 08:59:27 -07002546 if (!parseIpsProperties(aResp, properties))
2547 {
2548 messages::internalError(aResp->res);
2549 return;
2550 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002551 });
George Liue99073f2022-12-09 11:06:16 +08002552 });
Chris Cain37bbf982021-09-20 10:53:09 -05002553
2554 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2555}
2556
2557/**
2558 * @brief Sets Idle Power Saver properties.
2559 *
2560 * @param[in] aResp Shared pointer for generating response message.
2561 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2562 * RF request.
2563 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2564 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2565 * before entering idle state.
2566 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2567 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2568 * before exiting idle state
2569 *
2570 * @return None.
2571 */
2572inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2573 const std::optional<bool> ipsEnable,
2574 const std::optional<uint8_t> ipsEnterUtil,
2575 const std::optional<uint64_t> ipsEnterTime,
2576 const std::optional<uint8_t> ipsExitUtil,
2577 const std::optional<uint64_t> ipsExitTime)
2578{
2579 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2580
2581 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002582 constexpr std::array<std::string_view, 1> interfaces = {
2583 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2584 dbus::utility::getSubTree(
2585 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002586 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002587 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002588 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002589 if (ec)
2590 {
2591 BMCWEB_LOG_DEBUG
2592 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2593 << ec;
2594 messages::internalError(aResp->res);
2595 return;
2596 }
2597 if (subtree.empty())
2598 {
2599 // This is an optional D-Bus object, but user attempted to patch
2600 messages::resourceNotFound(aResp->res, "ComputerSystem",
2601 "IdlePowerSaver");
2602 return;
2603 }
2604 if (subtree.size() > 1)
2605 {
2606 // More then one PowerIdlePowerSaver object is not supported and
2607 // is an error
2608 BMCWEB_LOG_DEBUG
2609 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2610 << subtree.size();
2611 messages::internalError(aResp->res);
2612 return;
2613 }
2614 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2615 {
2616 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2617 messages::internalError(aResp->res);
2618 return;
2619 }
2620 const std::string& path = subtree[0].first;
2621 const std::string& service = subtree[0].second.begin()->first;
2622 if (service.empty())
2623 {
2624 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2625 messages::internalError(aResp->res);
2626 return;
2627 }
Chris Cain37bbf982021-09-20 10:53:09 -05002628
Ed Tanous002d39b2022-05-31 08:59:27 -07002629 // Valid Power IdlePowerSaver object found, now set any values that
2630 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002631
Ed Tanous002d39b2022-05-31 08:59:27 -07002632 if (ipsEnable)
2633 {
2634 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002635 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002636 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002637 {
Ed Tanous8a592812022-06-04 09:06:59 -07002638 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002639 messages::internalError(aResp->res);
2640 return;
2641 }
2642 },
2643 service, path, "org.freedesktop.DBus.Properties", "Set",
2644 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2645 dbus::utility::DbusVariantType(*ipsEnable));
2646 }
2647 if (ipsEnterUtil)
2648 {
2649 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002650 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002651 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002652 {
Ed Tanous8a592812022-06-04 09:06:59 -07002653 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002654 messages::internalError(aResp->res);
2655 return;
2656 }
2657 },
2658 service, path, "org.freedesktop.DBus.Properties", "Set",
2659 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2660 "EnterUtilizationPercent",
2661 dbus::utility::DbusVariantType(*ipsEnterUtil));
2662 }
2663 if (ipsEnterTime)
2664 {
2665 // Convert from seconds into milliseconds for DBus
2666 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2667 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002668 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002669 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002670 {
Ed Tanous8a592812022-06-04 09:06:59 -07002671 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002672 messages::internalError(aResp->res);
2673 return;
2674 }
2675 },
2676 service, path, "org.freedesktop.DBus.Properties", "Set",
2677 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2678 "EnterDwellTime",
2679 dbus::utility::DbusVariantType(timeMilliseconds));
2680 }
2681 if (ipsExitUtil)
2682 {
2683 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002684 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002685 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002686 {
Ed Tanous8a592812022-06-04 09:06:59 -07002687 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002688 messages::internalError(aResp->res);
2689 return;
2690 }
2691 },
2692 service, path, "org.freedesktop.DBus.Properties", "Set",
2693 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2694 "ExitUtilizationPercent",
2695 dbus::utility::DbusVariantType(*ipsExitUtil));
2696 }
2697 if (ipsExitTime)
2698 {
2699 // Convert from seconds into milliseconds for DBus
2700 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2701 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002702 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002703 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002704 {
Ed Tanous8a592812022-06-04 09:06:59 -07002705 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002706 messages::internalError(aResp->res);
2707 return;
2708 }
2709 },
2710 service, path, "org.freedesktop.DBus.Properties", "Set",
2711 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2712 "ExitDwellTime",
2713 dbus::utility::DbusVariantType(timeMilliseconds));
2714 }
George Liue99073f2022-12-09 11:06:16 +08002715 });
Chris Cain37bbf982021-09-20 10:53:09 -05002716
2717 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2718}
2719
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002720inline void handleComputerSystemHead(
2721 crow::App& app, const crow::Request& req,
2722 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2723{
2724 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2725 {
2726 return;
2727 }
2728 asyncResp->res.addHeader(
2729 boost::beast::http::field::link,
2730 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2731}
2732
Yong Lic45f0082019-10-10 14:19:01 +08002733/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002734 * SystemsCollection derived class for delivering ComputerSystems Collection
2735 * Schema
2736 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002737inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002738{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002739 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002740 .privileges(redfish::privileges::headComputerSystemCollection)
2741 .methods(boost::beast::http::verb::head)(
2742 std::bind_front(handleComputerSystemHead, std::ref(app)));
2743
2744 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002745 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002746 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002747 [&app](const crow::Request& req,
2748 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002749 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002750 {
2751 return;
2752 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002753
2754 asyncResp->res.addHeader(
2755 boost::beast::http::field::link,
2756 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002757 asyncResp->res.jsonValue["@odata.type"] =
2758 "#ComputerSystemCollection.ComputerSystemCollection";
2759 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2760 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002761
Ed Tanous002d39b2022-05-31 08:59:27 -07002762 sdbusplus::asio::getProperty<std::string>(
2763 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2764 "/xyz/openbmc_project/network/hypervisor",
2765 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002766 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002767 const std::string& /*hostName*/) {
2768 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2769 ifaceArray = nlohmann::json::array();
2770 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002771
Ed Tanous002d39b2022-05-31 08:59:27 -07002772 nlohmann::json::object_t system;
2773 system["@odata.id"] = "/redfish/v1/Systems/system";
2774 ifaceArray.push_back(std::move(system));
2775 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002776 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002777 {
2778 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2779 nlohmann::json::object_t hypervisor;
2780 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2781 ifaceArray.push_back(std::move(hypervisor));
2782 count = ifaceArray.size();
2783 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002784 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002785 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002786}
Sunitha Harish462023a2020-02-19 08:34:59 -06002787
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002788/**
2789 * Function transceives data with dbus directly.
2790 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002791inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002792{
Patrick Williams89492a12023-05-10 07:51:34 -05002793 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2794 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2795 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002796 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002797 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002798
2799 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002800 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002801 if (ec)
2802 {
2803 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2804 messages::internalError(asyncResp->res);
2805 return;
2806 }
2807 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002808 },
2809 serviceName, objectPath, interfaceName, method);
2810}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002811
2812/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002813 * SystemActionsReset class supports handle POST method for Reset action.
2814 * The class retrieves and sends data directly to D-Bus.
2815 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002816inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002817{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002818 /**
2819 * Function handles POST method request.
2820 * Analyzes POST body message before sends Reset request data to D-Bus.
2821 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002822 BMCWEB_ROUTE(app,
2823 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002824 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002825 .methods(boost::beast::http::verb::post)(
2826 [&app](const crow::Request& req,
2827 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002828 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002829 {
2830 return;
2831 }
2832 std::string resetType;
2833 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2834 resetType))
2835 {
2836 return;
2837 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002838
Ed Tanous002d39b2022-05-31 08:59:27 -07002839 // Get the command and host vs. chassis
2840 std::string command;
2841 bool hostCommand = true;
2842 if ((resetType == "On") || (resetType == "ForceOn"))
2843 {
2844 command = "xyz.openbmc_project.State.Host.Transition.On";
2845 hostCommand = true;
2846 }
2847 else if (resetType == "ForceOff")
2848 {
2849 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2850 hostCommand = false;
2851 }
2852 else if (resetType == "ForceRestart")
2853 {
2854 command =
2855 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2856 hostCommand = true;
2857 }
2858 else if (resetType == "GracefulShutdown")
2859 {
2860 command = "xyz.openbmc_project.State.Host.Transition.Off";
2861 hostCommand = true;
2862 }
2863 else if (resetType == "GracefulRestart")
2864 {
2865 command =
2866 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2867 hostCommand = true;
2868 }
2869 else if (resetType == "PowerCycle")
2870 {
2871 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2872 hostCommand = true;
2873 }
2874 else if (resetType == "Nmi")
2875 {
2876 doNMI(asyncResp);
2877 return;
2878 }
2879 else
2880 {
2881 messages::actionParameterUnknown(asyncResp->res, "Reset",
2882 resetType);
2883 return;
2884 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002885
Ed Tanous002d39b2022-05-31 08:59:27 -07002886 if (hostCommand)
2887 {
2888 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002889 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002890 if (ec)
2891 {
2892 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2893 if (ec.value() == boost::asio::error::invalid_argument)
2894 {
2895 messages::actionParameterNotSupported(
2896 asyncResp->res, resetType, "Reset");
2897 }
2898 else
2899 {
2900 messages::internalError(asyncResp->res);
2901 }
2902 return;
2903 }
2904 messages::success(asyncResp->res);
2905 },
2906 "xyz.openbmc_project.State.Host",
2907 "/xyz/openbmc_project/state/host0",
2908 "org.freedesktop.DBus.Properties", "Set",
2909 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2910 dbus::utility::DbusVariantType{command});
2911 }
2912 else
2913 {
2914 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002915 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002916 if (ec)
2917 {
2918 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2919 if (ec.value() == boost::asio::error::invalid_argument)
2920 {
2921 messages::actionParameterNotSupported(
2922 asyncResp->res, resetType, "Reset");
2923 }
2924 else
2925 {
2926 messages::internalError(asyncResp->res);
2927 }
2928 return;
2929 }
2930 messages::success(asyncResp->res);
2931 },
2932 "xyz.openbmc_project.State.Chassis",
2933 "/xyz/openbmc_project/state/chassis0",
2934 "org.freedesktop.DBus.Properties", "Set",
2935 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2936 dbus::utility::DbusVariantType{command});
2937 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002938 });
2939}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002940
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002941inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002942 App& app, const crow::Request& req,
2943 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2944{
2945 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2946 {
2947 return;
2948 }
2949
2950 asyncResp->res.addHeader(
2951 boost::beast::http::field::link,
2952 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2953}
2954
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002955inline void afterPortRequest(
2956 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2957 const boost::system::error_code& ec,
2958 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2959{
2960 if (ec)
2961 {
2962 messages::internalError(asyncResp->res);
2963 return;
2964 }
2965 for (const auto& data : socketData)
2966 {
2967 const std::string& socketPath = get<0>(data);
2968 const std::string& protocolName = get<1>(data);
2969 bool isProtocolEnabled = get<2>(data);
2970 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2971 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2972 // need to retrieve port number for
2973 // obmc-console-ssh service
2974 if (protocolName == "SSH")
2975 {
2976 getPortNumber(socketPath, [asyncResp, protocolName](
2977 const boost::system::error_code ec1,
2978 int portNumber) {
2979 if (ec1)
2980 {
2981 messages::internalError(asyncResp->res);
2982 return;
2983 }
2984 nlohmann::json& dataJson1 =
2985 asyncResp->res.jsonValue["SerialConsole"];
2986 dataJson1[protocolName]["Port"] = portNumber;
2987 });
2988 }
2989 }
2990}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002991/**
Ed Tanous66173382018-08-15 18:20:59 -07002992 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002993 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002994inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002995{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002996 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2997 .privileges(redfish::privileges::headComputerSystem)
2998 .methods(boost::beast::http::verb::head)(
2999 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07003000 /**
3001 * Functions triggers appropriate requests on DBus
3002 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003003 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003004 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003005 .methods(boost::beast::http::verb::get)(
3006 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003007 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3008 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003009 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003010 {
3011 return;
3012 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003013
3014 if (systemName == "hypervisor")
3015 {
3016 handleHypervisorSystemGet(asyncResp);
3017 return;
3018 }
3019
Ed Tanous22d268c2022-05-19 09:39:07 -07003020 if (systemName != "system")
3021 {
3022 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3023 systemName);
3024 return;
3025 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003026 asyncResp->res.addHeader(
3027 boost::beast::http::field::link,
3028 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003029 asyncResp->res.jsonValue["@odata.type"] =
3030 "#ComputerSystem.v1_16_0.ComputerSystem";
3031 asyncResp->res.jsonValue["Name"] = "system";
3032 asyncResp->res.jsonValue["Id"] = "system";
3033 asyncResp->res.jsonValue["SystemType"] = "Physical";
3034 asyncResp->res.jsonValue["Description"] = "Computer System";
3035 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3036 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3037 "Disabled";
3038 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3039 uint64_t(0);
3040 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3041 "Disabled";
3042 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003043
Ed Tanous002d39b2022-05-31 08:59:27 -07003044 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3045 "/redfish/v1/Systems/system/Processors";
3046 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3047 "/redfish/v1/Systems/system/Memory";
3048 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3049 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003050 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3051 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003052
Ed Tanous002d39b2022-05-31 08:59:27 -07003053 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3054 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3055 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3056 ["@Redfish.ActionInfo"] =
3057 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003058
Ed Tanous002d39b2022-05-31 08:59:27 -07003059 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3060 "/redfish/v1/Systems/system/LogServices";
3061 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3062 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003063
Ed Tanous002d39b2022-05-31 08:59:27 -07003064 nlohmann::json::array_t managedBy;
3065 nlohmann::json& manager = managedBy.emplace_back();
3066 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3067 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3068 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3069 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003070
Ed Tanous002d39b2022-05-31 08:59:27 -07003071 // Fill in SerialConsole info
3072 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3073 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3074 true;
Ed Tanous14766872022-03-15 10:44:42 -07003075
Ed Tanous002d39b2022-05-31 08:59:27 -07003076 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3077 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3078 true;
3079 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3080 asyncResp->res
3081 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3082 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003083 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3084 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003085
3086#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003087 // Fill in GraphicalConsole info
3088 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3089 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3090 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003091 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3092 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003093
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003094#endif // BMCWEB_ENABLE_KVM
George Liu7a1dbc42022-12-07 16:03:22 +08003095 constexpr std::array<std::string_view, 4> inventoryForSystems{
Ed Tanous002d39b2022-05-31 08:59:27 -07003096 "xyz.openbmc_project.Inventory.Item.Dimm",
3097 "xyz.openbmc_project.Inventory.Item.Cpu",
3098 "xyz.openbmc_project.Inventory.Item.Drive",
3099 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003100
Ed Tanous002d39b2022-05-31 08:59:27 -07003101 auto health = std::make_shared<HealthPopulate>(asyncResp);
George Liu7a1dbc42022-12-07 16:03:22 +08003102 dbus::utility::getSubTreePaths(
3103 "/", 0, inventoryForSystems,
3104 [health](const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07003105 const std::vector<std::string>& resp) {
3106 if (ec)
3107 {
3108 // no inventory
3109 return;
3110 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003111
Ed Tanous002d39b2022-05-31 08:59:27 -07003112 health->inventory = resp;
George Liu7a1dbc42022-12-07 16:03:22 +08003113 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003114
Ed Tanous002d39b2022-05-31 08:59:27 -07003115 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003116
Ed Tanous002d39b2022-05-31 08:59:27 -07003117 getMainChassisId(asyncResp,
3118 [](const std::string& chassisId,
3119 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3120 nlohmann::json::array_t chassisArray;
3121 nlohmann::json& chassis = chassisArray.emplace_back();
Willy Tueddfc432022-09-26 16:46:38 +00003122 chassis["@odata.id"] = crow::utility::urlFromPieces(
3123 "redfish", "v1", "Chassis", chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003124 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3125 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003126
Ed Tanous002d39b2022-05-31 08:59:27 -07003127 getLocationIndicatorActive(asyncResp);
3128 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3129 getIndicatorLedState(asyncResp);
3130 getComputerSystem(asyncResp, health);
3131 getHostState(asyncResp);
3132 getBootProperties(asyncResp);
3133 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003134 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003135 getPCIeDeviceList(asyncResp, "PCIeDevices");
3136 getHostWatchdogTimer(asyncResp);
3137 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003138 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003139 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003140#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003141 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003142#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003143 getTrustedModuleRequiredToBoot(asyncResp);
3144 getPowerMode(asyncResp);
3145 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003146 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003147
Ed Tanous22d268c2022-05-19 09:39:07 -07003148 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003149 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003150 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003151 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003152 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3153 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003154 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003155 {
3156 return;
3157 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003158 if (systemName != "system")
3159 {
3160 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3161 systemName);
3162 return;
3163 }
3164
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003165 asyncResp->res.addHeader(
3166 boost::beast::http::field::link,
3167 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3168
Ed Tanous002d39b2022-05-31 08:59:27 -07003169 std::optional<bool> locationIndicatorActive;
3170 std::optional<std::string> indicatorLed;
3171 std::optional<std::string> assetTag;
3172 std::optional<std::string> powerRestorePolicy;
3173 std::optional<std::string> powerMode;
3174 std::optional<bool> wdtEnable;
3175 std::optional<std::string> wdtTimeOutAction;
3176 std::optional<std::string> bootSource;
3177 std::optional<std::string> bootType;
3178 std::optional<std::string> bootEnable;
3179 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003180 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003181 std::optional<bool> bootTrustedModuleRequired;
3182 std::optional<bool> ipsEnable;
3183 std::optional<uint8_t> ipsEnterUtil;
3184 std::optional<uint64_t> ipsEnterTime;
3185 std::optional<uint8_t> ipsExitUtil;
3186 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003187
Ed Tanous002d39b2022-05-31 08:59:27 -07003188 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003189 if (!json_util::readJsonPatch(
3190 req, asyncResp->res,
3191 "IndicatorLED", indicatorLed,
3192 "LocationIndicatorActive", locationIndicatorActive,
3193 "AssetTag", assetTag,
3194 "PowerRestorePolicy", powerRestorePolicy,
3195 "PowerMode", powerMode,
3196 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3197 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3198 "Boot/BootSourceOverrideTarget", bootSource,
3199 "Boot/BootSourceOverrideMode", bootType,
3200 "Boot/BootSourceOverrideEnabled", bootEnable,
3201 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003202 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003203 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3204 "IdlePowerSaver/Enabled", ipsEnable,
3205 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3206 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3207 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3208 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3209 {
3210 return;
3211 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003212 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003213
Ed Tanous002d39b2022-05-31 08:59:27 -07003214 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003215
Ed Tanous002d39b2022-05-31 08:59:27 -07003216 if (assetTag)
3217 {
3218 setAssetTag(asyncResp, *assetTag);
3219 }
James Feistb49ac872019-05-21 15:12:01 -07003220
Ed Tanous002d39b2022-05-31 08:59:27 -07003221 if (wdtEnable || wdtTimeOutAction)
3222 {
3223 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3224 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003225
Ed Tanous002d39b2022-05-31 08:59:27 -07003226 if (bootSource || bootType || bootEnable)
3227 {
3228 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3229 }
3230 if (bootAutomaticRetry)
3231 {
3232 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3233 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003234
Corey Hardesty797d5da2022-04-26 17:54:52 +08003235 if (bootAutomaticRetryAttempts)
3236 {
3237 setAutomaticRetryAttempts(asyncResp,
3238 bootAutomaticRetryAttempts.value());
3239 }
3240
Ed Tanous002d39b2022-05-31 08:59:27 -07003241 if (bootTrustedModuleRequired)
3242 {
3243 setTrustedModuleRequiredToBoot(asyncResp,
3244 *bootTrustedModuleRequired);
3245 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003246
Ed Tanous002d39b2022-05-31 08:59:27 -07003247 if (locationIndicatorActive)
3248 {
3249 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3250 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003251
Ed Tanous002d39b2022-05-31 08:59:27 -07003252 // TODO (Gunnar): Remove IndicatorLED after enough time has
3253 // passed
3254 if (indicatorLed)
3255 {
3256 setIndicatorLedState(asyncResp, *indicatorLed);
3257 asyncResp->res.addHeader(boost::beast::http::field::warning,
3258 "299 - \"IndicatorLED is deprecated. Use "
3259 "LocationIndicatorActive instead.\"");
3260 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003261
Ed Tanous002d39b2022-05-31 08:59:27 -07003262 if (powerRestorePolicy)
3263 {
3264 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3265 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003266
Ed Tanous002d39b2022-05-31 08:59:27 -07003267 if (powerMode)
3268 {
3269 setPowerMode(asyncResp, *powerMode);
3270 }
Chris Cain37bbf982021-09-20 10:53:09 -05003271
Ed Tanous002d39b2022-05-31 08:59:27 -07003272 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3273 ipsExitTime)
3274 {
3275 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3276 ipsExitUtil, ipsExitTime);
3277 }
3278 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003279}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303280
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003281inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003282 crow::App& app, const crow::Request& req,
3283 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3284{
3285 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3286 {
3287 return;
3288 }
3289 asyncResp->res.addHeader(
3290 boost::beast::http::field::link,
3291 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3292}
3293
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303294/**
3295 * SystemResetActionInfo derived class for delivering Computer Systems
3296 * ResetType AllowableValues using ResetInfo schema.
3297 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003298inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303299{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003300 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3301 .privileges(redfish::privileges::headActionInfo)
3302 .methods(boost::beast::http::verb::head)(std::bind_front(
3303 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303304 /**
3305 * Functions triggers appropriate requests on DBus
3306 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003307 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003308 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003309 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003310 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003311 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3312 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003313 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003314 {
3315 return;
3316 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003317
3318 if (systemName == "hypervisor")
3319 {
3320 handleHypervisorResetActionGet(asyncResp);
3321 return;
3322 }
3323
Ed Tanous22d268c2022-05-19 09:39:07 -07003324 if (systemName != "system")
3325 {
3326 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3327 systemName);
3328 return;
3329 }
3330
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003331 asyncResp->res.addHeader(
3332 boost::beast::http::field::link,
3333 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003334
Ed Tanous002d39b2022-05-31 08:59:27 -07003335 asyncResp->res.jsonValue["@odata.id"] =
3336 "/redfish/v1/Systems/system/ResetActionInfo";
3337 asyncResp->res.jsonValue["@odata.type"] =
3338 "#ActionInfo.v1_1_2.ActionInfo";
3339 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3340 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003341
3342 nlohmann::json::array_t parameters;
3343 nlohmann::json::object_t parameter;
3344
3345 parameter["Name"] = "ResetType";
3346 parameter["Required"] = true;
3347 parameter["DataType"] = "String";
3348 nlohmann::json::array_t allowableValues;
3349 allowableValues.emplace_back("On");
3350 allowableValues.emplace_back("ForceOff");
3351 allowableValues.emplace_back("ForceOn");
3352 allowableValues.emplace_back("ForceRestart");
3353 allowableValues.emplace_back("GracefulRestart");
3354 allowableValues.emplace_back("GracefulShutdown");
3355 allowableValues.emplace_back("PowerCycle");
3356 allowableValues.emplace_back("Nmi");
3357 parameter["AllowableValues"] = std::move(allowableValues);
3358 parameters.emplace_back(std::move(parameter));
3359
3360 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003361 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003362}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003363} // namespace redfish