blob: c474d089933615ce3593c49a2da7591215ed4b0c [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 }
536 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700537 }
Ed Tanous66173382018-08-15 18:20:59 -0700538 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700539}
540
541/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700542 * @brief Retrieves host state properties over dbus
543 *
544 * @param[in] aResp Shared pointer for completing asynchronous calls.
545 *
546 * @return None.
547 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800548inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700549{
550 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700551 sdbusplus::asio::getProperty<std::string>(
552 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
553 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
554 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800555 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700556 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700557 if (ec)
558 {
559 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700560 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700561 // Service not available, no error, just don't return
562 // host state info
563 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700564 return;
565 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700566 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
567 messages::internalError(aResp->res);
568 return;
569 }
Ed Tanous66173382018-08-15 18:20:59 -0700570
Ed Tanous002d39b2022-05-31 08:59:27 -0700571 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
572 // Verify Host State
573 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
574 {
575 aResp->res.jsonValue["PowerState"] = "On";
576 aResp->res.jsonValue["Status"]["State"] = "Enabled";
577 }
578 else if (hostState ==
579 "xyz.openbmc_project.State.Host.HostState.Quiesced")
580 {
581 aResp->res.jsonValue["PowerState"] = "On";
582 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
583 }
584 else if (hostState ==
585 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
586 {
587 aResp->res.jsonValue["PowerState"] = "On";
588 aResp->res.jsonValue["Status"]["State"] = "InTest";
589 }
590 else if (
591 hostState ==
592 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
593 {
594 aResp->res.jsonValue["PowerState"] = "PoweringOn";
595 aResp->res.jsonValue["Status"]["State"] = "Starting";
596 }
597 else if (hostState ==
598 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
599 {
600 aResp->res.jsonValue["PowerState"] = "PoweringOff";
601 aResp->res.jsonValue["Status"]["State"] = "Disabled";
602 }
603 else
604 {
605 aResp->res.jsonValue["PowerState"] = "Off";
606 aResp->res.jsonValue["Status"]["State"] = "Disabled";
607 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700608 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700609}
610
611/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500612 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530613 *
614 * @param[in] dbusSource The boot source in DBUS speak.
615 *
616 * @return Returns as a string, the boot source in Redfish terms. If translation
617 * cannot be done, returns an empty string.
618 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000619inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530620{
621 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
622 {
623 return "None";
624 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700625 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530626 {
627 return "Hdd";
628 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700629 if (dbusSource ==
630 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530631 {
632 return "Cd";
633 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700634 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530635 {
636 return "Pxe";
637 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700638 if (dbusSource ==
639 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700640 {
641 return "Usb";
642 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700643 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530644}
645
646/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300647 * @brief Translates boot type DBUS property value to redfish.
648 *
649 * @param[in] dbusType The boot type in DBUS speak.
650 *
651 * @return Returns as a string, the boot type in Redfish terms. If translation
652 * cannot be done, returns an empty string.
653 */
654inline std::string dbusToRfBootType(const std::string& dbusType)
655{
656 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
657 {
658 return "Legacy";
659 }
660 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
661 {
662 return "UEFI";
663 }
664 return "";
665}
666
667/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500668 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530669 *
670 * @param[in] dbusMode The boot mode in DBUS speak.
671 *
672 * @return Returns as a string, the boot mode in Redfish terms. If translation
673 * cannot be done, returns an empty string.
674 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000675inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530676{
677 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
678 {
679 return "None";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530682 {
683 return "Diags";
684 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700685 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686 {
687 return "BiosSetup";
688 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700689 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530690}
691
692/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600693 * @brief Translates boot progress DBUS property value to redfish.
694 *
695 * @param[in] dbusBootProgress The boot progress in DBUS speak.
696 *
697 * @return Returns as a string, the boot progress in Redfish terms. If
698 * translation cannot be done, returns "None".
699 */
700inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
701{
702 // Now convert the D-Bus BootProgress to the appropriate Redfish
703 // enum
704 std::string rfBpLastState = "None";
705 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
706 "ProgressStages.Unspecified")
707 {
708 rfBpLastState = "None";
709 }
710 else if (dbusBootProgress ==
711 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
712 "PrimaryProcInit")
713 {
714 rfBpLastState = "PrimaryProcessorInitializationStarted";
715 }
716 else if (dbusBootProgress ==
717 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
718 "BusInit")
719 {
720 rfBpLastState = "BusInitializationStarted";
721 }
722 else if (dbusBootProgress ==
723 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
724 "MemoryInit")
725 {
726 rfBpLastState = "MemoryInitializationStarted";
727 }
728 else if (dbusBootProgress ==
729 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
730 "SecondaryProcInit")
731 {
732 rfBpLastState = "SecondaryProcessorInitializationStarted";
733 }
734 else if (dbusBootProgress ==
735 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
736 "PCIInit")
737 {
738 rfBpLastState = "PCIResourceConfigStarted";
739 }
740 else if (dbusBootProgress ==
741 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
742 "SystemSetup")
743 {
744 rfBpLastState = "SetupEntered";
745 }
746 else if (dbusBootProgress ==
747 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
748 "SystemInitComplete")
749 {
750 rfBpLastState = "SystemHardwareInitializationComplete";
751 }
752 else if (dbusBootProgress ==
753 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
754 "OSStart")
755 {
756 rfBpLastState = "OSBootStarted";
757 }
758 else if (dbusBootProgress ==
759 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
760 "OSRunning")
761 {
762 rfBpLastState = "OSRunning";
763 }
764 else
765 {
766 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
767 << dbusBootProgress;
768 // Just return the default
769 }
770 return rfBpLastState;
771}
772
773/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500774 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530775 *
776 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700777 * @param[out] bootSource The DBus source
778 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530779 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800782inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500783 const std::string& rfSource,
784 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530785{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300786 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
787 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700788
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530789 if (rfSource == "None")
790 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700791 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530792 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700793 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530794 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700795 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
796 }
797 else if (rfSource == "Hdd")
798 {
799 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
800 }
801 else if (rfSource == "Diags")
802 {
803 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
804 }
805 else if (rfSource == "Cd")
806 {
807 bootSource =
808 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
809 }
810 else if (rfSource == "BiosSetup")
811 {
812 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530813 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700814 else if (rfSource == "Usb")
815 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700816 bootSource =
817 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700818 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530819 else
820 {
George Liu0fda0f12021-11-16 10:06:17 +0800821 BMCWEB_LOG_DEBUG
822 << "Invalid property value for BootSourceOverrideTarget: "
823 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700824 messages::propertyValueNotInList(aResp->res, rfSource,
825 "BootSourceTargetOverride");
826 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530827 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700828 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530829}
Ali Ahmed19817712021-06-29 17:01:52 -0500830
Andrew Geissler978b8802020-11-19 13:36:40 -0600831/**
832 * @brief Retrieves boot progress of the system
833 *
834 * @param[in] aResp Shared pointer for generating response message.
835 *
836 * @return None.
837 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800838inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600839{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700840 sdbusplus::asio::getProperty<std::string>(
841 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
842 "/xyz/openbmc_project/state/host0",
843 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800844 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700845 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700846 if (ec)
847 {
848 // BootProgress is an optional object so just do nothing if
849 // not found
850 return;
851 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600852
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600854
Ed Tanous002d39b2022-05-31 08:59:27 -0700855 aResp->res.jsonValue["BootProgress"]["LastState"] =
856 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700857 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600858}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530859
860/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000861 * @brief Retrieves boot progress Last Update of the system
862 *
863 * @param[in] aResp Shared pointer for generating response message.
864 *
865 * @return None.
866 */
867inline void getBootProgressLastStateTime(
868 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
869{
870 sdbusplus::asio::getProperty<uint64_t>(
871 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
872 "/xyz/openbmc_project/state/host0",
873 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800874 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000875 const uint64_t lastStateTime) {
876 if (ec)
877 {
878 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
879 return;
880 }
881
882 // BootProgressLastUpdate is the last time the BootProgress property
883 // was updated. The time is the Epoch time, number of microseconds
884 // since 1 Jan 1970 00::00::00 UTC."
885 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
886 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
887
888 // Convert to ISO 8601 standard
889 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
890 redfish::time_utils::getDateTimeUintUs(lastStateTime);
891 });
892}
893
894/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300895 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300896 *
897 * @param[in] aResp Shared pointer for generating response message.
898 *
899 * @return None.
900 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300901
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300902inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300903{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700904 sdbusplus::asio::getProperty<std::string>(
905 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
906 "/xyz/openbmc_project/control/host0/boot",
907 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800908 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700909 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700910 if (ec)
911 {
912 // not an error, don't have to have the interface
913 return;
914 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300915
Ed Tanous002d39b2022-05-31 08:59:27 -0700916 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300917
Ed Tanous002d39b2022-05-31 08:59:27 -0700918 aResp->res.jsonValue["Boot"]
919 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700920 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300921
Ed Tanous002d39b2022-05-31 08:59:27 -0700922 auto rfType = dbusToRfBootType(bootType);
923 if (rfType.empty())
924 {
925 messages::internalError(aResp->res);
926 return;
927 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300928
Ed Tanous002d39b2022-05-31 08:59:27 -0700929 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700930 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300931}
932
933/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300934 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530935 *
936 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530937 *
938 * @return None.
939 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300940
941inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530942{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700943 sdbusplus::asio::getProperty<std::string>(
944 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
945 "/xyz/openbmc_project/control/host0/boot",
946 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800947 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700948 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700949 if (ec)
950 {
951 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
952 messages::internalError(aResp->res);
953 return;
954 }
955
956 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
957
958 aResp->res
959 .jsonValue["Boot"]
960 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
961 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
962
963 if (bootModeStr !=
964 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
965 {
966 auto rfMode = dbusToRfBootMode(bootModeStr);
967 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530968 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700969 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
970 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530971 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700972 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700973 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974}
975
976/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300977 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530978 *
979 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530980 *
981 * @return None.
982 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300983
984inline void
985 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700987 sdbusplus::asio::getProperty<std::string>(
988 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
989 "/xyz/openbmc_project/control/host0/boot",
990 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800991 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700992 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700993 if (ec)
994 {
995 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000996 if (ec.value() == boost::asio::error::host_unreachable)
997 {
998 return;
999 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001000 messages::internalError(aResp->res);
1001 return;
1002 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301003
Ed Tanous002d39b2022-05-31 08:59:27 -07001004 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301005
Ed Tanous002d39b2022-05-31 08:59:27 -07001006 auto rfSource = dbusToRfBootSource(bootSourceStr);
1007 if (!rfSource.empty())
1008 {
1009 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1010 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001011
Ed Tanous002d39b2022-05-31 08:59:27 -07001012 // Get BootMode as BootSourceOverrideTarget is constructed
1013 // from both BootSource and BootMode
1014 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001015 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301016}
1017
1018/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001019 * @brief This functions abstracts all the logic behind getting a
1020 * "BootSourceOverrideEnabled" property from an overall boot override enable
1021 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022 *
1023 * @param[in] aResp Shared pointer for generating response message.
1024 *
1025 * @return None.
1026 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301027
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001028inline void
1029 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1030 const bool bootOverrideEnableSetting)
1031{
1032 if (!bootOverrideEnableSetting)
1033 {
1034 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1035 return;
1036 }
1037
1038 // If boot source override is enabled, we need to check 'one_time'
1039 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001040 sdbusplus::asio::getProperty<bool>(
1041 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1042 "/xyz/openbmc_project/control/host0/boot/one_time",
1043 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001044 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001045 if (ec)
1046 {
1047 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1048 messages::internalError(aResp->res);
1049 return;
1050 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301051
Ed Tanous002d39b2022-05-31 08:59:27 -07001052 if (oneTimeSetting)
1053 {
1054 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1055 }
1056 else
1057 {
1058 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1059 "Continuous";
1060 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001061 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301062}
1063
1064/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001065 * @brief Retrieves boot override enable over DBUS
1066 *
1067 * @param[in] aResp Shared pointer for generating response message.
1068 *
1069 * @return None.
1070 */
1071
1072inline void
1073 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1074{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001075 sdbusplus::asio::getProperty<bool>(
1076 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1077 "/xyz/openbmc_project/control/host0/boot",
1078 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001079 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001080 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001081 if (ec)
1082 {
1083 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001084 if (ec.value() == boost::asio::error::host_unreachable)
1085 {
1086 return;
1087 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001088 messages::internalError(aResp->res);
1089 return;
1090 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001091
Ed Tanous002d39b2022-05-31 08:59:27 -07001092 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001093 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001094}
1095
1096/**
1097 * @brief Retrieves boot source override properties
1098 *
1099 * @param[in] aResp Shared pointer for generating response message.
1100 *
1101 * @return None.
1102 */
1103inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1104{
1105 BMCWEB_LOG_DEBUG << "Get boot information.";
1106
1107 getBootOverrideSource(aResp);
1108 getBootOverrideType(aResp);
1109 getBootOverrideEnable(aResp);
1110}
1111
1112/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001113 * @brief Retrieves the Last Reset Time
1114 *
1115 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1116 * and power off. Even though this is the "system" Redfish object look at the
1117 * chassis D-Bus interface for the LastStateChangeTime since this has the
1118 * last power operation time.
1119 *
1120 * @param[in] aResp Shared pointer for generating response message.
1121 *
1122 * @return None.
1123 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001124inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001125{
1126 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1127
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001128 sdbusplus::asio::getProperty<uint64_t>(
1129 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1130 "/xyz/openbmc_project/state/chassis0",
1131 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001132 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001133 if (ec)
1134 {
1135 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1136 return;
1137 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001138
Ed Tanous002d39b2022-05-31 08:59:27 -07001139 // LastStateChangeTime is epoch time, in milliseconds
1140 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1141 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001142
Ed Tanous002d39b2022-05-31 08:59:27 -07001143 // Convert to ISO 8601 standard
1144 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001145 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001146 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001147}
1148
1149/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001150 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1151 *
1152 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1153 * corresponding property "AttemptsLeft" that keeps track of the amount of
1154 * automatic retry attempts left are hosted in phosphor-state-manager through
1155 * dbus.
1156 *
1157 * @param[in] aResp Shared pointer for generating response message.
1158 *
1159 * @return None.
1160 */
1161inline void
1162 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1163{
1164 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1165
1166 sdbusplus::asio::getAllProperties(
1167 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1168 "/xyz/openbmc_project/state/host0",
1169 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1170 [aResp{aResp}](const boost::system::error_code& ec,
1171 const dbus::utility::DBusPropertiesMap& propertiesList) {
1172 if (ec)
1173 {
1174 if (ec.value() != EBADR)
1175 {
1176 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1177 messages::internalError(aResp->res);
1178 }
1179 return;
1180 }
1181
1182 const uint32_t* attemptsLeft = nullptr;
1183 const uint32_t* retryAttempts = nullptr;
1184
1185 const bool success = sdbusplus::unpackPropertiesNoThrow(
1186 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1187 attemptsLeft, "RetryAttempts", retryAttempts);
1188
1189 if (!success)
1190 {
1191 messages::internalError(aResp->res);
1192 return;
1193 }
1194
1195 if (attemptsLeft != nullptr)
1196 {
1197 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1198 *attemptsLeft;
1199 }
1200
1201 if (retryAttempts != nullptr)
1202 {
1203 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1204 *retryAttempts;
1205 }
1206 });
1207}
1208
1209/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001210 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1211 *
1212 * @param[in] aResp Shared pointer for generating response message.
1213 *
1214 * @return None.
1215 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001216inline void
1217 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001218{
1219 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1220
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001221 sdbusplus::asio::getProperty<bool>(
1222 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1223 "/xyz/openbmc_project/control/host0/auto_reboot",
1224 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001225 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001226 if (ec)
1227 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001228 if (ec.value() != EBADR)
1229 {
1230 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1231 messages::internalError(aResp->res);
1232 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001233 return;
1234 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001235
Ed Tanous002d39b2022-05-31 08:59:27 -07001236 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1237 if (autoRebootEnabled)
1238 {
1239 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1240 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001241 }
1242 else
1243 {
1244 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1245 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001246 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001247
Ed Tanous002d39b2022-05-31 08:59:27 -07001248 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1249 // and RetryAttempts. OpenBMC only supports Disabled and
1250 // RetryAttempts.
1251 aResp->res.jsonValue["Boot"]
1252 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1253 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001254 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001255}
1256
1257/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001258 * @brief Sets RetryAttempts
1259 *
1260 * @param[in] aResp Shared pointer for generating response message.
1261 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1262 *
1263 *@return None.
1264 */
1265
1266inline void
1267 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1268 const uint32_t retryAttempts)
1269{
1270 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1271 crow::connections::systemBus->async_method_call(
1272 [aResp](const boost::system::error_code& ec) {
1273 if (ec)
1274 {
1275 BMCWEB_LOG_ERROR
1276 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1277 messages::internalError(aResp->res);
1278 return;
1279 }
1280 },
1281 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1282 "org.freedesktop.DBus.Properties", "Set",
1283 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1284 std::variant<uint32_t>(retryAttempts));
1285}
1286
1287/**
George Liuc6a620f2020-04-10 17:18:11 +08001288 * @brief Retrieves power restore policy over DBUS.
1289 *
1290 * @param[in] aResp Shared pointer for generating response message.
1291 *
1292 * @return None.
1293 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001294inline void
1295 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001296{
1297 BMCWEB_LOG_DEBUG << "Get power restore policy";
1298
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001299 sdbusplus::asio::getProperty<std::string>(
1300 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1301 "/xyz/openbmc_project/control/host0/power_restore_policy",
1302 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001303 [aResp](const boost::system::error_code& ec,
1304 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001305 if (ec)
1306 {
1307 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1308 return;
1309 }
George Liuc6a620f2020-04-10 17:18:11 +08001310
Ed Tanous002d39b2022-05-31 08:59:27 -07001311 const boost::container::flat_map<std::string, std::string> policyMaps = {
1312 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1313 "AlwaysOn"},
1314 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1315 "AlwaysOff"},
1316 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1317 "LastState"},
1318 // Return `AlwaysOff` when power restore policy set to "None"
1319 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1320 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001321
Ed Tanous002d39b2022-05-31 08:59:27 -07001322 auto policyMapsIt = policyMaps.find(policy);
1323 if (policyMapsIt == policyMaps.end())
1324 {
1325 messages::internalError(aResp->res);
1326 return;
1327 }
George Liuc6a620f2020-04-10 17:18:11 +08001328
Ed Tanous002d39b2022-05-31 08:59:27 -07001329 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001330 });
George Liuc6a620f2020-04-10 17:18:11 +08001331}
1332
1333/**
Ali Ahmed19817712021-06-29 17:01:52 -05001334 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1335 * TPM is required for booting the host.
1336 *
1337 * @param[in] aResp Shared pointer for generating response message.
1338 *
1339 * @return None.
1340 */
1341inline void getTrustedModuleRequiredToBoot(
1342 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1343{
1344 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001345 constexpr std::array<std::string_view, 1> interfaces = {
1346 "xyz.openbmc_project.Control.TPM.Policy"};
1347 dbus::utility::getSubTree(
1348 "/", 0, interfaces,
1349 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001350 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001351 if (ec)
1352 {
1353 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1354 << ec;
1355 // This is an optional D-Bus object so just return if
1356 // error occurs
1357 return;
1358 }
1359 if (subtree.empty())
1360 {
1361 // As noted above, this is an optional interface so just return
1362 // if there is no instance found
1363 return;
1364 }
1365
1366 /* When there is more than one TPMEnable object... */
1367 if (subtree.size() > 1)
1368 {
1369 BMCWEB_LOG_DEBUG
1370 << "DBUS response has more than 1 TPM Enable object:"
1371 << subtree.size();
1372 // Throw an internal Error and return
1373 messages::internalError(aResp->res);
1374 return;
1375 }
1376
1377 // Make sure the Dbus response map has a service and objectPath
1378 // field
1379 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1380 {
1381 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1382 messages::internalError(aResp->res);
1383 return;
1384 }
1385
1386 const std::string& path = subtree[0].first;
1387 const std::string& serv = subtree[0].second.begin()->first;
1388
1389 // Valid TPM Enable object found, now reading the current value
1390 sdbusplus::asio::getProperty<bool>(
1391 *crow::connections::systemBus, serv, path,
1392 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001393 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001394 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001395 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001396 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001397 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001398 messages::internalError(aResp->res);
1399 return;
1400 }
1401
Ed Tanous002d39b2022-05-31 08:59:27 -07001402 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001403 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001404 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1405 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001406 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001407 else
1408 {
1409 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1410 "Disabled";
1411 }
1412 });
George Liue99073f2022-12-09 11:06:16 +08001413 });
Ali Ahmed19817712021-06-29 17:01:52 -05001414}
1415
1416/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001417 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1418 * TPM is required for booting the host.
1419 *
1420 * @param[in] aResp Shared pointer for generating response message.
1421 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1422 *
1423 * @return None.
1424 */
1425inline void setTrustedModuleRequiredToBoot(
1426 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1427{
1428 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001429 constexpr std::array<std::string_view, 1> interfaces = {
1430 "xyz.openbmc_project.Control.TPM.Policy"};
1431 dbus::utility::getSubTree(
1432 "/", 0, interfaces,
1433 [aResp,
1434 tpmRequired](const boost::system::error_code& ec,
1435 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001436 if (ec)
1437 {
1438 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1439 << ec;
1440 messages::internalError(aResp->res);
1441 return;
1442 }
1443 if (subtree.empty())
1444 {
1445 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1446 "TrustedModuleRequiredToBoot");
1447 return;
1448 }
1449
1450 /* When there is more than one TPMEnable object... */
1451 if (subtree.size() > 1)
1452 {
1453 BMCWEB_LOG_DEBUG
1454 << "DBUS response has more than 1 TPM Enable object:"
1455 << subtree.size();
1456 // Throw an internal Error and return
1457 messages::internalError(aResp->res);
1458 return;
1459 }
1460
1461 // Make sure the Dbus response map has a service and objectPath
1462 // field
1463 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1464 {
1465 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1466 messages::internalError(aResp->res);
1467 return;
1468 }
1469
1470 const std::string& path = subtree[0].first;
1471 const std::string& serv = subtree[0].second.begin()->first;
1472
1473 if (serv.empty())
1474 {
1475 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1476 messages::internalError(aResp->res);
1477 return;
1478 }
1479
1480 // Valid TPM Enable object found, now setting the value
1481 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001482 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001483 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001484 {
1485 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001486 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001487 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001488 messages::internalError(aResp->res);
1489 return;
1490 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001491 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1492 },
1493 serv, path, "org.freedesktop.DBus.Properties", "Set",
1494 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1495 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001496 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001497}
1498
1499/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301500 * @brief Sets boot properties into DBUS object(s).
1501 *
1502 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001503 * @param[in] bootType The boot type to set.
1504 * @return Integer error code.
1505 */
1506inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001507 const std::optional<std::string>& bootType)
1508{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001509 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001510
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001511 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001512 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001513 return;
1514 }
1515
1516 // Source target specified
1517 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1518 // Figure out which DBUS interface and property to use
1519 if (*bootType == "Legacy")
1520 {
1521 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1522 }
1523 else if (*bootType == "UEFI")
1524 {
1525 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1526 }
1527 else
1528 {
1529 BMCWEB_LOG_DEBUG << "Invalid property value for "
1530 "BootSourceOverrideMode: "
1531 << *bootType;
1532 messages::propertyValueNotInList(aResp->res, *bootType,
1533 "BootSourceOverrideMode");
1534 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001535 }
1536
1537 // Act on validated parameters
1538 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1539
1540 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001541 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001542 if (ec)
1543 {
1544 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1545 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001546 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001547 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001548 return;
1549 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001550 messages::internalError(aResp->res);
1551 return;
1552 }
1553 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001554 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001555 "xyz.openbmc_project.Settings",
1556 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001557 "org.freedesktop.DBus.Properties", "Set",
1558 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001559 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001560}
1561
1562/**
1563 * @brief Sets boot properties into DBUS object(s).
1564 *
1565 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001566 * @param[in] bootType The boot type to set.
1567 * @return Integer error code.
1568 */
1569inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1570 const std::optional<std::string>& bootEnable)
1571{
1572 if (!bootEnable)
1573 {
1574 return;
1575 }
1576 // Source target specified
1577 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1578
1579 bool bootOverrideEnable = false;
1580 bool bootOverridePersistent = false;
1581 // Figure out which DBUS interface and property to use
1582 if (*bootEnable == "Disabled")
1583 {
1584 bootOverrideEnable = false;
1585 }
1586 else if (*bootEnable == "Once")
1587 {
1588 bootOverrideEnable = true;
1589 bootOverridePersistent = false;
1590 }
1591 else if (*bootEnable == "Continuous")
1592 {
1593 bootOverrideEnable = true;
1594 bootOverridePersistent = true;
1595 }
1596 else
1597 {
George Liu0fda0f12021-11-16 10:06:17 +08001598 BMCWEB_LOG_DEBUG
1599 << "Invalid property value for BootSourceOverrideEnabled: "
1600 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001601 messages::propertyValueNotInList(aResp->res, *bootEnable,
1602 "BootSourceOverrideEnabled");
1603 return;
1604 }
1605
1606 // Act on validated parameters
1607 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1608
1609 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001610 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001611 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001612 {
Ed Tanous8a592812022-06-04 09:06:59 -07001613 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001614 messages::internalError(aResp->res);
1615 return;
1616 }
1617 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001618 },
1619 "xyz.openbmc_project.Settings",
1620 "/xyz/openbmc_project/control/host0/boot",
1621 "org.freedesktop.DBus.Properties", "Set",
1622 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001623 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001624
1625 if (!bootOverrideEnable)
1626 {
1627 return;
1628 }
1629
1630 // In case boot override is enabled we need to set correct value for the
1631 // 'one_time' enable DBus interface
1632 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1633 << bootOverridePersistent;
1634
1635 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001636 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001637 if (ec)
1638 {
1639 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1640 messages::internalError(aResp->res);
1641 return;
1642 }
1643 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001644 },
1645 "xyz.openbmc_project.Settings",
1646 "/xyz/openbmc_project/control/host0/boot/one_time",
1647 "org.freedesktop.DBus.Properties", "Set",
1648 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001649 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001650}
1651
1652/**
1653 * @brief Sets boot properties into DBUS object(s).
1654 *
1655 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301656 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301657 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001658 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301659 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001660inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001661 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301662{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001663 std::string bootSourceStr;
1664 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001665
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001666 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301667 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001668 return;
1669 }
1670
1671 // Source target specified
1672 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1673 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001674 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1675 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001676 {
1677 BMCWEB_LOG_DEBUG
1678 << "Invalid property value for BootSourceOverrideTarget: "
1679 << *bootSource;
1680 messages::propertyValueNotInList(aResp->res, *bootSource,
1681 "BootSourceTargetOverride");
1682 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001683 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301684
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001685 // Act on validated parameters
1686 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1687 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001688
1689 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001690 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001691 if (ec)
1692 {
1693 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1694 messages::internalError(aResp->res);
1695 return;
1696 }
1697 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001698 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001699 "xyz.openbmc_project.Settings",
1700 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001701 "org.freedesktop.DBus.Properties", "Set",
1702 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001703 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001704
1705 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001706 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001707 if (ec)
1708 {
1709 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1710 messages::internalError(aResp->res);
1711 return;
1712 }
1713 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001714 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001715 "xyz.openbmc_project.Settings",
1716 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001717 "org.freedesktop.DBus.Properties", "Set",
1718 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001719 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001720}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001721
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001722/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001723 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301724 *
1725 * @param[in] aResp Shared pointer for generating response message.
1726 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001727 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301728 * @param[in] bootEnable The boot override enable from incoming RF request.
1729 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001730 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301731 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001732
1733inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1734 const std::optional<std::string>& bootSource,
1735 const std::optional<std::string>& bootType,
1736 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301737{
1738 BMCWEB_LOG_DEBUG << "Set boot information.";
1739
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001740 setBootModeOrSource(aResp, bootSource);
1741 setBootType(aResp, bootType);
1742 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301743}
1744
George Liuc6a620f2020-04-10 17:18:11 +08001745/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001746 * @brief Sets AssetTag
1747 *
1748 * @param[in] aResp Shared pointer for generating response message.
1749 * @param[in] assetTag "AssetTag" from request.
1750 *
1751 * @return None.
1752 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001753inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001754 const std::string& assetTag)
1755{
George Liue99073f2022-12-09 11:06:16 +08001756 constexpr std::array<std::string_view, 1> interfaces = {
1757 "xyz.openbmc_project.Inventory.Item.System"};
1758 dbus::utility::getSubTree(
1759 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001760 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001761 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001762 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001763 if (ec)
1764 {
1765 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1766 messages::internalError(aResp->res);
1767 return;
1768 }
1769 if (subtree.empty())
1770 {
1771 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1772 messages::internalError(aResp->res);
1773 return;
1774 }
1775 // Assume only 1 system D-Bus object
1776 // Throw an error if there is more than 1
1777 if (subtree.size() > 1)
1778 {
1779 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1780 messages::internalError(aResp->res);
1781 return;
1782 }
1783 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1784 {
1785 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1786 messages::internalError(aResp->res);
1787 return;
1788 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001789
Ed Tanous002d39b2022-05-31 08:59:27 -07001790 const std::string& path = subtree[0].first;
1791 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001792
Ed Tanous002d39b2022-05-31 08:59:27 -07001793 if (service.empty())
1794 {
1795 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1796 messages::internalError(aResp->res);
1797 return;
1798 }
1799
1800 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001801 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001802 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001803 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001804 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1805 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001806 messages::internalError(aResp->res);
1807 return;
1808 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001809 },
1810 service, path, "org.freedesktop.DBus.Properties", "Set",
1811 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1812 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001813 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001814}
1815
1816/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001817 * @brief Sets automaticRetry (Auto Reboot)
1818 *
1819 * @param[in] aResp Shared pointer for generating response message.
1820 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1821 *
1822 * @return None.
1823 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001824inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001825 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001826{
1827 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1828
1829 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001830 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001831
1832 if (automaticRetryConfig == "Disabled")
1833 {
1834 autoRebootEnabled = false;
1835 }
1836 else if (automaticRetryConfig == "RetryAttempts")
1837 {
1838 autoRebootEnabled = true;
1839 }
1840 else
1841 {
George Liu0fda0f12021-11-16 10:06:17 +08001842 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001843 << automaticRetryConfig;
1844 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1845 "AutomaticRetryConfig");
1846 return;
1847 }
1848
1849 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001850 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001851 if (ec)
1852 {
1853 messages::internalError(aResp->res);
1854 return;
1855 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001856 },
1857 "xyz.openbmc_project.Settings",
1858 "/xyz/openbmc_project/control/host0/auto_reboot",
1859 "org.freedesktop.DBus.Properties", "Set",
1860 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001861 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001862}
1863
1864/**
George Liuc6a620f2020-04-10 17:18:11 +08001865 * @brief Sets power restore policy properties.
1866 *
1867 * @param[in] aResp Shared pointer for generating response message.
1868 * @param[in] policy power restore policy properties from request.
1869 *
1870 * @return None.
1871 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001872inline void
1873 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1874 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001875{
1876 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1877
1878 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001879 {"AlwaysOn",
1880 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1881 {"AlwaysOff",
1882 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1883 {"LastState",
1884 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001885
1886 std::string powerRestorPolicy;
1887
Gunnar Mills4e69c902021-01-05 19:50:11 -06001888 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001889 if (policyMapsIt == policyMaps.end())
1890 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001891 messages::propertyValueNotInList(aResp->res, policy,
1892 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001893 return;
1894 }
1895
1896 powerRestorPolicy = policyMapsIt->second;
1897
1898 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001899 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001900 if (ec)
1901 {
1902 messages::internalError(aResp->res);
1903 return;
1904 }
George Liuc6a620f2020-04-10 17:18:11 +08001905 },
1906 "xyz.openbmc_project.Settings",
1907 "/xyz/openbmc_project/control/host0/power_restore_policy",
1908 "org.freedesktop.DBus.Properties", "Set",
1909 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001910 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001911}
1912
AppaRao Pulia6349912019-10-18 17:16:08 +05301913#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1914/**
1915 * @brief Retrieves provisioning status
1916 *
1917 * @param[in] aResp Shared pointer for completing asynchronous calls.
1918 *
1919 * @return None.
1920 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001921inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301922{
1923 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001924 sdbusplus::asio::getAllProperties(
1925 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1926 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001927 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001928 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001929 nlohmann::json& oemPFR =
1930 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1931 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1932 "#OemComputerSystem.OpenBmc";
1933 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001934
Ed Tanous002d39b2022-05-31 08:59:27 -07001935 if (ec)
1936 {
1937 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1938 // not an error, don't have to have the interface
1939 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1940 return;
1941 }
1942
1943 const bool* provState = nullptr;
1944 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001945
1946 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001947 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1948 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001949
1950 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001951 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001952 messages::internalError(aResp->res);
1953 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001954 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301955
Ed Tanous002d39b2022-05-31 08:59:27 -07001956 if ((provState == nullptr) || (lockState == nullptr))
1957 {
1958 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1959 messages::internalError(aResp->res);
1960 return;
1961 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301962
Ed Tanous002d39b2022-05-31 08:59:27 -07001963 if (*provState == true)
1964 {
1965 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301966 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001967 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301968 }
1969 else
1970 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001971 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301972 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001973 }
1974 else
1975 {
1976 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1977 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001978 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301979}
1980#endif
1981
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301982/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001983 * @brief Translate the PowerMode to a response message.
1984 *
1985 * @param[in] aResp Shared pointer for generating response message.
1986 * @param[in] modeValue PowerMode value to be translated
1987 *
1988 * @return None.
1989 */
1990inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1991 const std::string& modeValue)
1992{
George Liu0fda0f12021-11-16 10:06:17 +08001993 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001994 {
1995 aResp->res.jsonValue["PowerMode"] = "Static";
1996 }
George Liu0fda0f12021-11-16 10:06:17 +08001997 else if (
1998 modeValue ==
1999 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002000 {
2001 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2002 }
George Liu0fda0f12021-11-16 10:06:17 +08002003 else if (modeValue ==
2004 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002005 {
2006 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2007 }
George Liu0fda0f12021-11-16 10:06:17 +08002008 else if (modeValue ==
2009 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002010 {
2011 aResp->res.jsonValue["PowerMode"] = "OEM";
2012 }
2013 else
2014 {
2015 // Any other values would be invalid
2016 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2017 messages::internalError(aResp->res);
2018 }
2019}
2020
2021/**
2022 * @brief Retrieves system power mode
2023 *
2024 * @param[in] aResp Shared pointer for generating response message.
2025 *
2026 * @return None.
2027 */
2028inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2029{
2030 BMCWEB_LOG_DEBUG << "Get power mode.";
2031
2032 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002033 constexpr std::array<std::string_view, 1> interfaces = {
2034 "xyz.openbmc_project.Control.Power.Mode"};
2035 dbus::utility::getSubTree(
2036 "/", 0, interfaces,
2037 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002038 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002039 if (ec)
2040 {
2041 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2042 << ec;
2043 // This is an optional D-Bus object so just return if
2044 // error occurs
2045 return;
2046 }
2047 if (subtree.empty())
2048 {
2049 // As noted above, this is an optional interface so just return
2050 // if there is no instance found
2051 return;
2052 }
2053 if (subtree.size() > 1)
2054 {
2055 // More then one PowerMode object is not supported and is an
2056 // error
2057 BMCWEB_LOG_DEBUG
2058 << "Found more than 1 system D-Bus Power.Mode objects: "
2059 << subtree.size();
2060 messages::internalError(aResp->res);
2061 return;
2062 }
2063 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2064 {
2065 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2066 messages::internalError(aResp->res);
2067 return;
2068 }
2069 const std::string& path = subtree[0].first;
2070 const std::string& service = subtree[0].second.begin()->first;
2071 if (service.empty())
2072 {
2073 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2074 messages::internalError(aResp->res);
2075 return;
2076 }
2077 // Valid Power Mode object found, now read the current value
2078 sdbusplus::asio::getProperty<std::string>(
2079 *crow::connections::systemBus, service, path,
2080 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002081 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002082 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002083 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002084 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002085 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002086 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002087 messages::internalError(aResp->res);
2088 return;
2089 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002090
Ed Tanous002d39b2022-05-31 08:59:27 -07002091 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2092 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002093
Ed Tanous002d39b2022-05-31 08:59:27 -07002094 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2095 translatePowerMode(aResp, pmode);
2096 });
George Liue99073f2022-12-09 11:06:16 +08002097 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002098}
2099
2100/**
2101 * @brief Validate the specified mode is valid and return the PowerMode
2102 * name associated with that string
2103 *
2104 * @param[in] aResp Shared pointer for generating response message.
2105 * @param[in] modeString String representing the desired PowerMode
2106 *
2107 * @return PowerMode value or empty string if mode is not valid
2108 */
2109inline std::string
2110 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2111 const std::string& modeString)
2112{
2113 std::string mode;
2114
2115 if (modeString == "Static")
2116 {
2117 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2118 }
2119 else if (modeString == "MaximumPerformance")
2120 {
George Liu0fda0f12021-11-16 10:06:17 +08002121 mode =
2122 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002123 }
2124 else if (modeString == "PowerSaving")
2125 {
2126 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2127 }
2128 else
2129 {
2130 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2131 }
2132 return mode;
2133}
2134
2135/**
2136 * @brief Sets system power mode.
2137 *
2138 * @param[in] aResp Shared pointer for generating response message.
2139 * @param[in] pmode System power mode from request.
2140 *
2141 * @return None.
2142 */
2143inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2144 const std::string& pmode)
2145{
2146 BMCWEB_LOG_DEBUG << "Set power mode.";
2147
2148 std::string powerMode = validatePowerMode(aResp, pmode);
2149 if (powerMode.empty())
2150 {
2151 return;
2152 }
2153
2154 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002155 constexpr std::array<std::string_view, 1> interfaces = {
2156 "xyz.openbmc_project.Control.Power.Mode"};
2157 dbus::utility::getSubTree(
2158 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002159 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002160 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002161 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002162 if (ec)
2163 {
2164 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2165 << ec;
2166 // This is an optional D-Bus object, but user attempted to patch
2167 messages::internalError(aResp->res);
2168 return;
2169 }
2170 if (subtree.empty())
2171 {
2172 // This is an optional D-Bus object, but user attempted to patch
2173 messages::resourceNotFound(aResp->res, "ComputerSystem",
2174 "PowerMode");
2175 return;
2176 }
2177 if (subtree.size() > 1)
2178 {
2179 // More then one PowerMode object is not supported and is an
2180 // error
2181 BMCWEB_LOG_DEBUG
2182 << "Found more than 1 system D-Bus Power.Mode objects: "
2183 << subtree.size();
2184 messages::internalError(aResp->res);
2185 return;
2186 }
2187 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2188 {
2189 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2190 messages::internalError(aResp->res);
2191 return;
2192 }
2193 const std::string& path = subtree[0].first;
2194 const std::string& service = subtree[0].second.begin()->first;
2195 if (service.empty())
2196 {
2197 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2198 messages::internalError(aResp->res);
2199 return;
2200 }
2201
2202 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2203 << path;
2204
2205 // Set the Power Mode property
2206 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002207 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002208 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002209 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002210 messages::internalError(aResp->res);
2211 return;
2212 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002213 },
2214 service, path, "org.freedesktop.DBus.Properties", "Set",
2215 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2216 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002217 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002218}
2219
2220/**
Yong Li51709ff2019-09-30 14:13:04 +08002221 * @brief Translates watchdog timeout action DBUS property value to redfish.
2222 *
2223 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2224 *
2225 * @return Returns as a string, the timeout action in Redfish terms. If
2226 * translation cannot be done, returns an empty string.
2227 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002228inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002229{
2230 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2231 {
2232 return "None";
2233 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002234 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002235 {
2236 return "ResetSystem";
2237 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002238 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002239 {
2240 return "PowerDown";
2241 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002242 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002243 {
2244 return "PowerCycle";
2245 }
2246
2247 return "";
2248}
2249
2250/**
Yong Lic45f0082019-10-10 14:19:01 +08002251 *@brief Translates timeout action from Redfish to DBUS property value.
2252 *
2253 *@param[in] rfAction The timeout action in Redfish.
2254 *
2255 *@return Returns as a string, the time_out action as expected by DBUS.
2256 *If translation cannot be done, returns an empty string.
2257 */
2258
Ed Tanous23a21a12020-07-25 04:45:05 +00002259inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002260{
2261 if (rfAction == "None")
2262 {
2263 return "xyz.openbmc_project.State.Watchdog.Action.None";
2264 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002265 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002266 {
2267 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2268 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002269 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002270 {
2271 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2272 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002273 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002274 {
2275 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2276 }
2277
2278 return "";
2279}
2280
2281/**
Yong Li51709ff2019-09-30 14:13:04 +08002282 * @brief Retrieves host watchdog timer properties over DBUS
2283 *
2284 * @param[in] aResp Shared pointer for completing asynchronous calls.
2285 *
2286 * @return None.
2287 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002288inline void
2289 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002290{
2291 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002292 sdbusplus::asio::getAllProperties(
2293 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2294 "/xyz/openbmc_project/watchdog/host0",
2295 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002296 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002297 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002298 if (ec)
2299 {
2300 // watchdog service is stopped
2301 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2302 return;
2303 }
2304
2305 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2306
2307 nlohmann::json& hostWatchdogTimer =
2308 aResp->res.jsonValue["HostWatchdogTimer"];
2309
2310 // watchdog service is running/enabled
2311 hostWatchdogTimer["Status"]["State"] = "Enabled";
2312
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002313 const bool* enabled = nullptr;
2314 const std::string* expireAction = nullptr;
2315
2316 const bool success = sdbusplus::unpackPropertiesNoThrow(
2317 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2318 "ExpireAction", expireAction);
2319
2320 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002321 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002322 messages::internalError(aResp->res);
2323 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002324 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002325
2326 if (enabled != nullptr)
2327 {
2328 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2329 }
2330
2331 if (expireAction != nullptr)
2332 {
2333 std::string action = dbusToRfWatchdogAction(*expireAction);
2334 if (action.empty())
2335 {
2336 messages::internalError(aResp->res);
2337 return;
2338 }
2339 hostWatchdogTimer["TimeoutAction"] = action;
2340 }
2341 });
Yong Li51709ff2019-09-30 14:13:04 +08002342}
2343
2344/**
Yong Lic45f0082019-10-10 14:19:01 +08002345 * @brief Sets Host WatchDog Timer properties.
2346 *
2347 * @param[in] aResp Shared pointer for generating response message.
2348 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2349 * RF request.
2350 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2351 *
2352 * @return None.
2353 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002354inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002355 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002356 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002357{
2358 BMCWEB_LOG_DEBUG << "Set host watchdog";
2359
2360 if (wdtTimeOutAction)
2361 {
2362 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2363 // check if TimeOut Action is Valid
2364 if (wdtTimeOutActStr.empty())
2365 {
2366 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2367 << *wdtTimeOutAction;
2368 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2369 "TimeoutAction");
2370 return;
2371 }
2372
2373 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002374 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002375 if (ec)
2376 {
2377 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2378 messages::internalError(aResp->res);
2379 return;
2380 }
Yong Lic45f0082019-10-10 14:19:01 +08002381 },
2382 "xyz.openbmc_project.Watchdog",
2383 "/xyz/openbmc_project/watchdog/host0",
2384 "org.freedesktop.DBus.Properties", "Set",
2385 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002386 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002387 }
2388
2389 if (wdtEnable)
2390 {
2391 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002392 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002393 if (ec)
2394 {
2395 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2396 messages::internalError(aResp->res);
2397 return;
2398 }
Yong Lic45f0082019-10-10 14:19:01 +08002399 },
2400 "xyz.openbmc_project.Watchdog",
2401 "/xyz/openbmc_project/watchdog/host0",
2402 "org.freedesktop.DBus.Properties", "Set",
2403 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002404 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002405 }
2406}
2407
Chris Cain37bbf982021-09-20 10:53:09 -05002408/**
2409 * @brief Parse the Idle Power Saver properties into json
2410 *
2411 * @param[in] aResp Shared pointer for completing asynchronous calls.
2412 * @param[in] properties IPS property data from DBus.
2413 *
2414 * @return true if successful
2415 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002416inline bool
2417 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2418 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002419{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002420 const bool* enabled = nullptr;
2421 const uint8_t* enterUtilizationPercent = nullptr;
2422 const uint64_t* enterDwellTime = nullptr;
2423 const uint8_t* exitUtilizationPercent = nullptr;
2424 const uint64_t* exitDwellTime = nullptr;
2425
2426 const bool success = sdbusplus::unpackPropertiesNoThrow(
2427 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002428 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2429 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2430 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002431
2432 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002433 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002434 return false;
2435 }
2436
2437 if (enabled != nullptr)
2438 {
2439 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2440 }
2441
2442 if (enterUtilizationPercent != nullptr)
2443 {
2444 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2445 *enterUtilizationPercent;
2446 }
2447
2448 if (enterDwellTime != nullptr)
2449 {
2450 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2451 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2452 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2453 .count();
2454 }
2455
2456 if (exitUtilizationPercent != nullptr)
2457 {
2458 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2459 *exitUtilizationPercent;
2460 }
2461
2462 if (exitDwellTime != nullptr)
2463 {
2464 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2465 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2466 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2467 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002468 }
2469
2470 return true;
2471}
2472
2473/**
2474 * @brief Retrieves host watchdog timer properties over DBUS
2475 *
2476 * @param[in] aResp Shared pointer for completing asynchronous calls.
2477 *
2478 * @return None.
2479 */
2480inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2481{
2482 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2483
2484 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002485 constexpr std::array<std::string_view, 1> interfaces = {
2486 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2487 dbus::utility::getSubTree(
2488 "/", 0, interfaces,
2489 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002490 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002491 if (ec)
2492 {
2493 BMCWEB_LOG_DEBUG
2494 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2495 << ec;
2496 messages::internalError(aResp->res);
2497 return;
2498 }
2499 if (subtree.empty())
2500 {
2501 // This is an optional interface so just return
2502 // if there is no instance found
2503 BMCWEB_LOG_DEBUG << "No instances found";
2504 return;
2505 }
2506 if (subtree.size() > 1)
2507 {
2508 // More then one PowerIdlePowerSaver object is not supported and
2509 // is an error
2510 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2511 "Power.IdlePowerSaver objects: "
2512 << subtree.size();
2513 messages::internalError(aResp->res);
2514 return;
2515 }
2516 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2517 {
2518 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2519 messages::internalError(aResp->res);
2520 return;
2521 }
2522 const std::string& path = subtree[0].first;
2523 const std::string& service = subtree[0].second.begin()->first;
2524 if (service.empty())
2525 {
2526 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2527 messages::internalError(aResp->res);
2528 return;
2529 }
2530
2531 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002532 sdbusplus::asio::getAllProperties(
2533 *crow::connections::systemBus, service, path,
2534 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002535 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002536 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002537 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002538 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002539 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002540 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002541 messages::internalError(aResp->res);
2542 return;
2543 }
2544
Ed Tanous002d39b2022-05-31 08:59:27 -07002545 if (!parseIpsProperties(aResp, properties))
2546 {
2547 messages::internalError(aResp->res);
2548 return;
2549 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002550 });
George Liue99073f2022-12-09 11:06:16 +08002551 });
Chris Cain37bbf982021-09-20 10:53:09 -05002552
2553 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2554}
2555
2556/**
2557 * @brief Sets Idle Power Saver properties.
2558 *
2559 * @param[in] aResp Shared pointer for generating response message.
2560 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2561 * RF request.
2562 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2563 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2564 * before entering idle state.
2565 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2566 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2567 * before exiting idle state
2568 *
2569 * @return None.
2570 */
2571inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2572 const std::optional<bool> ipsEnable,
2573 const std::optional<uint8_t> ipsEnterUtil,
2574 const std::optional<uint64_t> ipsEnterTime,
2575 const std::optional<uint8_t> ipsExitUtil,
2576 const std::optional<uint64_t> ipsExitTime)
2577{
2578 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2579
2580 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002581 constexpr std::array<std::string_view, 1> interfaces = {
2582 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2583 dbus::utility::getSubTree(
2584 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002585 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002586 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002587 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002588 if (ec)
2589 {
2590 BMCWEB_LOG_DEBUG
2591 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2592 << ec;
2593 messages::internalError(aResp->res);
2594 return;
2595 }
2596 if (subtree.empty())
2597 {
2598 // This is an optional D-Bus object, but user attempted to patch
2599 messages::resourceNotFound(aResp->res, "ComputerSystem",
2600 "IdlePowerSaver");
2601 return;
2602 }
2603 if (subtree.size() > 1)
2604 {
2605 // More then one PowerIdlePowerSaver object is not supported and
2606 // is an error
2607 BMCWEB_LOG_DEBUG
2608 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2609 << subtree.size();
2610 messages::internalError(aResp->res);
2611 return;
2612 }
2613 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2614 {
2615 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2616 messages::internalError(aResp->res);
2617 return;
2618 }
2619 const std::string& path = subtree[0].first;
2620 const std::string& service = subtree[0].second.begin()->first;
2621 if (service.empty())
2622 {
2623 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2624 messages::internalError(aResp->res);
2625 return;
2626 }
Chris Cain37bbf982021-09-20 10:53:09 -05002627
Ed Tanous002d39b2022-05-31 08:59:27 -07002628 // Valid Power IdlePowerSaver object found, now set any values that
2629 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002630
Ed Tanous002d39b2022-05-31 08:59:27 -07002631 if (ipsEnable)
2632 {
2633 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002634 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002635 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002636 {
Ed Tanous8a592812022-06-04 09:06:59 -07002637 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002638 messages::internalError(aResp->res);
2639 return;
2640 }
2641 },
2642 service, path, "org.freedesktop.DBus.Properties", "Set",
2643 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2644 dbus::utility::DbusVariantType(*ipsEnable));
2645 }
2646 if (ipsEnterUtil)
2647 {
2648 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002649 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002650 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002651 {
Ed Tanous8a592812022-06-04 09:06:59 -07002652 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002653 messages::internalError(aResp->res);
2654 return;
2655 }
2656 },
2657 service, path, "org.freedesktop.DBus.Properties", "Set",
2658 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2659 "EnterUtilizationPercent",
2660 dbus::utility::DbusVariantType(*ipsEnterUtil));
2661 }
2662 if (ipsEnterTime)
2663 {
2664 // Convert from seconds into milliseconds for DBus
2665 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2666 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002667 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002668 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002669 {
Ed Tanous8a592812022-06-04 09:06:59 -07002670 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002671 messages::internalError(aResp->res);
2672 return;
2673 }
2674 },
2675 service, path, "org.freedesktop.DBus.Properties", "Set",
2676 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2677 "EnterDwellTime",
2678 dbus::utility::DbusVariantType(timeMilliseconds));
2679 }
2680 if (ipsExitUtil)
2681 {
2682 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002683 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002684 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002685 {
Ed Tanous8a592812022-06-04 09:06:59 -07002686 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002687 messages::internalError(aResp->res);
2688 return;
2689 }
2690 },
2691 service, path, "org.freedesktop.DBus.Properties", "Set",
2692 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2693 "ExitUtilizationPercent",
2694 dbus::utility::DbusVariantType(*ipsExitUtil));
2695 }
2696 if (ipsExitTime)
2697 {
2698 // Convert from seconds into milliseconds for DBus
2699 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2700 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002701 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002702 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002703 {
Ed Tanous8a592812022-06-04 09:06:59 -07002704 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002705 messages::internalError(aResp->res);
2706 return;
2707 }
2708 },
2709 service, path, "org.freedesktop.DBus.Properties", "Set",
2710 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2711 "ExitDwellTime",
2712 dbus::utility::DbusVariantType(timeMilliseconds));
2713 }
George Liue99073f2022-12-09 11:06:16 +08002714 });
Chris Cain37bbf982021-09-20 10:53:09 -05002715
2716 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2717}
2718
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002719inline void handleComputerSystemHead(
2720 crow::App& app, const crow::Request& req,
2721 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2722{
2723 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2724 {
2725 return;
2726 }
2727 asyncResp->res.addHeader(
2728 boost::beast::http::field::link,
2729 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2730}
2731
Yong Lic45f0082019-10-10 14:19:01 +08002732/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002733 * SystemsCollection derived class for delivering ComputerSystems Collection
2734 * Schema
2735 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002736inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002737{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002738 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002739 .privileges(redfish::privileges::headComputerSystemCollection)
2740 .methods(boost::beast::http::verb::head)(
2741 std::bind_front(handleComputerSystemHead, std::ref(app)));
2742
2743 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002744 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002745 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002746 [&app](const crow::Request& req,
2747 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002748 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002749 {
2750 return;
2751 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002752
2753 asyncResp->res.addHeader(
2754 boost::beast::http::field::link,
2755 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002756 asyncResp->res.jsonValue["@odata.type"] =
2757 "#ComputerSystemCollection.ComputerSystemCollection";
2758 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2759 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002760
Ed Tanous002d39b2022-05-31 08:59:27 -07002761 sdbusplus::asio::getProperty<std::string>(
2762 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2763 "/xyz/openbmc_project/network/hypervisor",
2764 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002765 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002766 const std::string& /*hostName*/) {
2767 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2768 ifaceArray = nlohmann::json::array();
2769 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002770
Ed Tanous002d39b2022-05-31 08:59:27 -07002771 nlohmann::json::object_t system;
2772 system["@odata.id"] = "/redfish/v1/Systems/system";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002773 ifaceArray.emplace_back(std::move(system));
Ed Tanous002d39b2022-05-31 08:59:27 -07002774 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002775 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002776 {
2777 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2778 nlohmann::json::object_t hypervisor;
2779 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002780 ifaceArray.emplace_back(std::move(hypervisor));
Ed Tanous002d39b2022-05-31 08:59:27 -07002781 count = ifaceArray.size();
2782 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002783 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002784 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002785}
Sunitha Harish462023a2020-02-19 08:34:59 -06002786
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002787/**
2788 * Function transceives data with dbus directly.
2789 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002790inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002791{
Patrick Williams89492a12023-05-10 07:51:34 -05002792 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2793 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2794 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002795 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002796 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002797
2798 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002799 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002800 if (ec)
2801 {
2802 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2803 messages::internalError(asyncResp->res);
2804 return;
2805 }
2806 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002807 },
2808 serviceName, objectPath, interfaceName, method);
2809}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002810
2811/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002812 * SystemActionsReset class supports handle POST method for Reset action.
2813 * The class retrieves and sends data directly to D-Bus.
2814 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002815inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002816{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002817 /**
2818 * Function handles POST method request.
2819 * Analyzes POST body message before sends Reset request data to D-Bus.
2820 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002821 BMCWEB_ROUTE(app,
2822 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002823 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002824 .methods(boost::beast::http::verb::post)(
2825 [&app](const crow::Request& req,
2826 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002827 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002828 {
2829 return;
2830 }
2831 std::string resetType;
2832 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2833 resetType))
2834 {
2835 return;
2836 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002837
Ed Tanous002d39b2022-05-31 08:59:27 -07002838 // Get the command and host vs. chassis
2839 std::string command;
2840 bool hostCommand = true;
2841 if ((resetType == "On") || (resetType == "ForceOn"))
2842 {
2843 command = "xyz.openbmc_project.State.Host.Transition.On";
2844 hostCommand = true;
2845 }
2846 else if (resetType == "ForceOff")
2847 {
2848 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2849 hostCommand = false;
2850 }
2851 else if (resetType == "ForceRestart")
2852 {
2853 command =
2854 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2855 hostCommand = true;
2856 }
2857 else if (resetType == "GracefulShutdown")
2858 {
2859 command = "xyz.openbmc_project.State.Host.Transition.Off";
2860 hostCommand = true;
2861 }
2862 else if (resetType == "GracefulRestart")
2863 {
2864 command =
2865 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2866 hostCommand = true;
2867 }
2868 else if (resetType == "PowerCycle")
2869 {
2870 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2871 hostCommand = true;
2872 }
2873 else if (resetType == "Nmi")
2874 {
2875 doNMI(asyncResp);
2876 return;
2877 }
2878 else
2879 {
2880 messages::actionParameterUnknown(asyncResp->res, "Reset",
2881 resetType);
2882 return;
2883 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002884
Ed Tanous002d39b2022-05-31 08:59:27 -07002885 if (hostCommand)
2886 {
2887 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002888 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002889 if (ec)
2890 {
2891 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2892 if (ec.value() == boost::asio::error::invalid_argument)
2893 {
2894 messages::actionParameterNotSupported(
2895 asyncResp->res, resetType, "Reset");
2896 }
2897 else
2898 {
2899 messages::internalError(asyncResp->res);
2900 }
2901 return;
2902 }
2903 messages::success(asyncResp->res);
2904 },
2905 "xyz.openbmc_project.State.Host",
2906 "/xyz/openbmc_project/state/host0",
2907 "org.freedesktop.DBus.Properties", "Set",
2908 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2909 dbus::utility::DbusVariantType{command});
2910 }
2911 else
2912 {
2913 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002914 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002915 if (ec)
2916 {
2917 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2918 if (ec.value() == boost::asio::error::invalid_argument)
2919 {
2920 messages::actionParameterNotSupported(
2921 asyncResp->res, resetType, "Reset");
2922 }
2923 else
2924 {
2925 messages::internalError(asyncResp->res);
2926 }
2927 return;
2928 }
2929 messages::success(asyncResp->res);
2930 },
2931 "xyz.openbmc_project.State.Chassis",
2932 "/xyz/openbmc_project/state/chassis0",
2933 "org.freedesktop.DBus.Properties", "Set",
2934 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2935 dbus::utility::DbusVariantType{command});
2936 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002937 });
2938}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002939
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002940inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002941 App& app, const crow::Request& req,
2942 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2943{
2944 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2945 {
2946 return;
2947 }
2948
2949 asyncResp->res.addHeader(
2950 boost::beast::http::field::link,
2951 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2952}
2953
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002954inline void afterPortRequest(
2955 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2956 const boost::system::error_code& ec,
2957 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2958{
2959 if (ec)
2960 {
2961 messages::internalError(asyncResp->res);
2962 return;
2963 }
2964 for (const auto& data : socketData)
2965 {
2966 const std::string& socketPath = get<0>(data);
2967 const std::string& protocolName = get<1>(data);
2968 bool isProtocolEnabled = get<2>(data);
2969 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2970 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2971 // need to retrieve port number for
2972 // obmc-console-ssh service
2973 if (protocolName == "SSH")
2974 {
2975 getPortNumber(socketPath, [asyncResp, protocolName](
2976 const boost::system::error_code ec1,
2977 int portNumber) {
2978 if (ec1)
2979 {
2980 messages::internalError(asyncResp->res);
2981 return;
2982 }
2983 nlohmann::json& dataJson1 =
2984 asyncResp->res.jsonValue["SerialConsole"];
2985 dataJson1[protocolName]["Port"] = portNumber;
2986 });
2987 }
2988 }
2989}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002990/**
Ed Tanous66173382018-08-15 18:20:59 -07002991 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002992 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002993inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002994{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002995 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2996 .privileges(redfish::privileges::headComputerSystem)
2997 .methods(boost::beast::http::verb::head)(
2998 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07002999 /**
3000 * Functions triggers appropriate requests on DBus
3001 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003002 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003003 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003004 .methods(boost::beast::http::verb::get)(
3005 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003006 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3007 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003008 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003009 {
3010 return;
3011 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003012
3013 if (systemName == "hypervisor")
3014 {
3015 handleHypervisorSystemGet(asyncResp);
3016 return;
3017 }
3018
Ed Tanous22d268c2022-05-19 09:39:07 -07003019 if (systemName != "system")
3020 {
3021 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3022 systemName);
3023 return;
3024 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003025 asyncResp->res.addHeader(
3026 boost::beast::http::field::link,
3027 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003028 asyncResp->res.jsonValue["@odata.type"] =
3029 "#ComputerSystem.v1_16_0.ComputerSystem";
3030 asyncResp->res.jsonValue["Name"] = "system";
3031 asyncResp->res.jsonValue["Id"] = "system";
3032 asyncResp->res.jsonValue["SystemType"] = "Physical";
3033 asyncResp->res.jsonValue["Description"] = "Computer System";
3034 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3035 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3036 "Disabled";
3037 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3038 uint64_t(0);
3039 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3040 "Disabled";
3041 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003042
Ed Tanous002d39b2022-05-31 08:59:27 -07003043 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3044 "/redfish/v1/Systems/system/Processors";
3045 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3046 "/redfish/v1/Systems/system/Memory";
3047 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3048 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003049 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3050 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003051
Ed Tanous002d39b2022-05-31 08:59:27 -07003052 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3053 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3054 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3055 ["@Redfish.ActionInfo"] =
3056 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003057
Ed Tanous002d39b2022-05-31 08:59:27 -07003058 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3059 "/redfish/v1/Systems/system/LogServices";
3060 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3061 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003062
Ed Tanous002d39b2022-05-31 08:59:27 -07003063 nlohmann::json::array_t managedBy;
3064 nlohmann::json& manager = managedBy.emplace_back();
3065 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3066 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3067 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3068 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003069
Ed Tanous002d39b2022-05-31 08:59:27 -07003070 // Fill in SerialConsole info
3071 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3072 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3073 true;
Ed Tanous14766872022-03-15 10:44:42 -07003074
Ed Tanous002d39b2022-05-31 08:59:27 -07003075 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3076 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3077 true;
3078 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3079 asyncResp->res
3080 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3081 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003082 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3083 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003084
3085#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003086 // Fill in GraphicalConsole info
3087 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3088 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3089 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003090 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3091 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003092
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003093#endif // BMCWEB_ENABLE_KVM
George Liu7a1dbc42022-12-07 16:03:22 +08003094 constexpr std::array<std::string_view, 4> inventoryForSystems{
Ed Tanous002d39b2022-05-31 08:59:27 -07003095 "xyz.openbmc_project.Inventory.Item.Dimm",
3096 "xyz.openbmc_project.Inventory.Item.Cpu",
3097 "xyz.openbmc_project.Inventory.Item.Drive",
3098 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003099
Ed Tanous002d39b2022-05-31 08:59:27 -07003100 auto health = std::make_shared<HealthPopulate>(asyncResp);
George Liu7a1dbc42022-12-07 16:03:22 +08003101 dbus::utility::getSubTreePaths(
3102 "/", 0, inventoryForSystems,
3103 [health](const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07003104 const std::vector<std::string>& resp) {
3105 if (ec)
3106 {
3107 // no inventory
3108 return;
3109 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003110
Ed Tanous002d39b2022-05-31 08:59:27 -07003111 health->inventory = resp;
George Liu7a1dbc42022-12-07 16:03:22 +08003112 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003113
Ed Tanous002d39b2022-05-31 08:59:27 -07003114 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003115
Ed Tanous002d39b2022-05-31 08:59:27 -07003116 getMainChassisId(asyncResp,
3117 [](const std::string& chassisId,
3118 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3119 nlohmann::json::array_t chassisArray;
3120 nlohmann::json& chassis = chassisArray.emplace_back();
Willy Tueddfc432022-09-26 16:46:38 +00003121 chassis["@odata.id"] = crow::utility::urlFromPieces(
3122 "redfish", "v1", "Chassis", chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003123 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3124 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003125
Ed Tanous002d39b2022-05-31 08:59:27 -07003126 getLocationIndicatorActive(asyncResp);
3127 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3128 getIndicatorLedState(asyncResp);
3129 getComputerSystem(asyncResp, health);
3130 getHostState(asyncResp);
3131 getBootProperties(asyncResp);
3132 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003133 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003134 getPCIeDeviceList(asyncResp, "PCIeDevices");
3135 getHostWatchdogTimer(asyncResp);
3136 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003137 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003138 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003139#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003140 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003141#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003142 getTrustedModuleRequiredToBoot(asyncResp);
3143 getPowerMode(asyncResp);
3144 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003145 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003146
Ed Tanous22d268c2022-05-19 09:39:07 -07003147 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003148 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003149 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003150 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003151 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3152 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003153 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003154 {
3155 return;
3156 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003157 if (systemName != "system")
3158 {
3159 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3160 systemName);
3161 return;
3162 }
3163
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003164 asyncResp->res.addHeader(
3165 boost::beast::http::field::link,
3166 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3167
Ed Tanous002d39b2022-05-31 08:59:27 -07003168 std::optional<bool> locationIndicatorActive;
3169 std::optional<std::string> indicatorLed;
3170 std::optional<std::string> assetTag;
3171 std::optional<std::string> powerRestorePolicy;
3172 std::optional<std::string> powerMode;
3173 std::optional<bool> wdtEnable;
3174 std::optional<std::string> wdtTimeOutAction;
3175 std::optional<std::string> bootSource;
3176 std::optional<std::string> bootType;
3177 std::optional<std::string> bootEnable;
3178 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003179 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003180 std::optional<bool> bootTrustedModuleRequired;
3181 std::optional<bool> ipsEnable;
3182 std::optional<uint8_t> ipsEnterUtil;
3183 std::optional<uint64_t> ipsEnterTime;
3184 std::optional<uint8_t> ipsExitUtil;
3185 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003186
Ed Tanous002d39b2022-05-31 08:59:27 -07003187 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003188 if (!json_util::readJsonPatch(
3189 req, asyncResp->res,
3190 "IndicatorLED", indicatorLed,
3191 "LocationIndicatorActive", locationIndicatorActive,
3192 "AssetTag", assetTag,
3193 "PowerRestorePolicy", powerRestorePolicy,
3194 "PowerMode", powerMode,
3195 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3196 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3197 "Boot/BootSourceOverrideTarget", bootSource,
3198 "Boot/BootSourceOverrideMode", bootType,
3199 "Boot/BootSourceOverrideEnabled", bootEnable,
3200 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003201 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003202 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3203 "IdlePowerSaver/Enabled", ipsEnable,
3204 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3205 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3206 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3207 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3208 {
3209 return;
3210 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003211 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003212
Ed Tanous002d39b2022-05-31 08:59:27 -07003213 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003214
Ed Tanous002d39b2022-05-31 08:59:27 -07003215 if (assetTag)
3216 {
3217 setAssetTag(asyncResp, *assetTag);
3218 }
James Feistb49ac872019-05-21 15:12:01 -07003219
Ed Tanous002d39b2022-05-31 08:59:27 -07003220 if (wdtEnable || wdtTimeOutAction)
3221 {
3222 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3223 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003224
Ed Tanous002d39b2022-05-31 08:59:27 -07003225 if (bootSource || bootType || bootEnable)
3226 {
3227 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3228 }
3229 if (bootAutomaticRetry)
3230 {
3231 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3232 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003233
Corey Hardesty797d5da2022-04-26 17:54:52 +08003234 if (bootAutomaticRetryAttempts)
3235 {
3236 setAutomaticRetryAttempts(asyncResp,
3237 bootAutomaticRetryAttempts.value());
3238 }
3239
Ed Tanous002d39b2022-05-31 08:59:27 -07003240 if (bootTrustedModuleRequired)
3241 {
3242 setTrustedModuleRequiredToBoot(asyncResp,
3243 *bootTrustedModuleRequired);
3244 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003245
Ed Tanous002d39b2022-05-31 08:59:27 -07003246 if (locationIndicatorActive)
3247 {
3248 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3249 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003250
Ed Tanous002d39b2022-05-31 08:59:27 -07003251 // TODO (Gunnar): Remove IndicatorLED after enough time has
3252 // passed
3253 if (indicatorLed)
3254 {
3255 setIndicatorLedState(asyncResp, *indicatorLed);
3256 asyncResp->res.addHeader(boost::beast::http::field::warning,
3257 "299 - \"IndicatorLED is deprecated. Use "
3258 "LocationIndicatorActive instead.\"");
3259 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003260
Ed Tanous002d39b2022-05-31 08:59:27 -07003261 if (powerRestorePolicy)
3262 {
3263 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3264 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003265
Ed Tanous002d39b2022-05-31 08:59:27 -07003266 if (powerMode)
3267 {
3268 setPowerMode(asyncResp, *powerMode);
3269 }
Chris Cain37bbf982021-09-20 10:53:09 -05003270
Ed Tanous002d39b2022-05-31 08:59:27 -07003271 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3272 ipsExitTime)
3273 {
3274 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3275 ipsExitUtil, ipsExitTime);
3276 }
3277 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003278}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303279
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003280inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003281 crow::App& app, const crow::Request& req,
3282 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3283{
3284 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3285 {
3286 return;
3287 }
3288 asyncResp->res.addHeader(
3289 boost::beast::http::field::link,
3290 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3291}
3292
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303293/**
3294 * SystemResetActionInfo derived class for delivering Computer Systems
3295 * ResetType AllowableValues using ResetInfo schema.
3296 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003297inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303298{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003299 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3300 .privileges(redfish::privileges::headActionInfo)
3301 .methods(boost::beast::http::verb::head)(std::bind_front(
3302 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303303 /**
3304 * Functions triggers appropriate requests on DBus
3305 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003306 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003307 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003308 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003309 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003310 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3311 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003312 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003313 {
3314 return;
3315 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003316
3317 if (systemName == "hypervisor")
3318 {
3319 handleHypervisorResetActionGet(asyncResp);
3320 return;
3321 }
3322
Ed Tanous22d268c2022-05-19 09:39:07 -07003323 if (systemName != "system")
3324 {
3325 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3326 systemName);
3327 return;
3328 }
3329
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003330 asyncResp->res.addHeader(
3331 boost::beast::http::field::link,
3332 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003333
Ed Tanous002d39b2022-05-31 08:59:27 -07003334 asyncResp->res.jsonValue["@odata.id"] =
3335 "/redfish/v1/Systems/system/ResetActionInfo";
3336 asyncResp->res.jsonValue["@odata.type"] =
3337 "#ActionInfo.v1_1_2.ActionInfo";
3338 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3339 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003340
3341 nlohmann::json::array_t parameters;
3342 nlohmann::json::object_t parameter;
3343
3344 parameter["Name"] = "ResetType";
3345 parameter["Required"] = true;
3346 parameter["DataType"] = "String";
3347 nlohmann::json::array_t allowableValues;
3348 allowableValues.emplace_back("On");
3349 allowableValues.emplace_back("ForceOff");
3350 allowableValues.emplace_back("ForceOn");
3351 allowableValues.emplace_back("ForceRestart");
3352 allowableValues.emplace_back("GracefulRestart");
3353 allowableValues.emplace_back("GracefulShutdown");
3354 allowableValues.emplace_back("PowerCycle");
3355 allowableValues.emplace_back("Nmi");
3356 parameter["AllowableValues"] = std::move(allowableValues);
3357 parameters.emplace_back(std::move(parameter));
3358
3359 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003360 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003361}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003362} // namespace redfish