blob: 4a607489ca41a923157c31339f79c6ef9098e007 [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>
Ed Tanousef4c65b2023-04-24 15:28:50 -070035#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070036#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020037#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050038
George Liu7a1dbc42022-12-07 16:03:22 +080039#include <array>
40#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080041#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020042
Ed Tanous1abe55e2018-09-05 08:30:59 -070043namespace redfish
44{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020045
Abhishek Patel5c3e9272021-06-24 10:11:33 -050046const static std::array<std::pair<std::string_view, std::string_view>, 2>
47 protocolToDBusForSystems{
48 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
49
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050/**
51 * @brief Updates the Functional State of DIMMs
52 *
53 * @param[in] aResp Shared pointer for completing asynchronous calls
54 * @param[in] dimmState Dimm's Functional state, true/false
55 *
56 * @return None.
57 */
zhanghch058d1b46d2021-04-01 11:18:24 +080058inline void
59 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070060 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050061{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070062 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050063
Gunnar Mills4e0453b2020-07-08 14:00:30 -050064 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065 // Update STATE only if previous State was DISABLED and current Dimm is
66 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070067 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050068 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
69 if (prevMemSummary == "Disabled")
70 {
Ed Tanouse05aec52022-01-25 10:28:56 -080071 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050072 {
73 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
74 "Enabled";
75 }
76 }
77}
78
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050080 * @brief Update "ProcessorSummary" "Status" "State" based on
81 * CPU Functional State
82 *
83 * @param[in] aResp Shared pointer for completing asynchronous calls
84 * @param[in] cpuFunctionalState is CPU functional true/false
85 *
86 * @return None.
87 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070088inline void
89 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
90 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070092 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093
Ed Tanous02cad962022-06-30 16:50:15 -070094 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050095 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
96
Gunnar Mills4e0453b2020-07-08 14:00:30 -050097 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050098 // Update STATE only if previous State was Non_Functional and current CPU is
99 // Functional.
100 if (prevProcState == "Disabled")
101 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800102 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103 {
104 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
105 "Enabled";
106 }
107 }
108}
109
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500110/*
111 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
112 *
113 * @param[in] aResp Shared pointer for completing asynchronous calls
114 * @param[in] cpuPresenceState CPU present or not
115 *
116 * @return None.
117 */
118inline void
119 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
120 bool isCpuPresent)
121{
122 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
123
124 if (isCpuPresent)
125 {
126 nlohmann::json& procCount =
127 aResp->res.jsonValue["ProcessorSummary"]["Count"];
128 auto* procCountPtr =
129 procCount.get_ptr<nlohmann::json::number_integer_t*>();
130 if (procCountPtr != nullptr)
131 {
132 // shouldn't be possible to be nullptr
133 *procCountPtr += 1;
134 }
135 }
136}
137
Ali Ahmed382d6472021-09-03 16:53:53 -0500138inline void getProcessorProperties(
139 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
140 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
141 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500142{
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
144
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200145 // TODO: Get Model
146
147 const uint16_t* coreCount = nullptr;
148
149 const bool success = sdbusplus::unpackPropertiesNoThrow(
150 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
151
152 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200154 messages::internalError(aResp->res);
155 return;
156 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500157
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200158 if (coreCount != nullptr)
159 {
160 nlohmann::json& coreCountJson =
161 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
162 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500163
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200164 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200166 coreCountJson = *coreCount;
167 }
168 else
169 {
170 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500171 }
172 }
173}
174
175/*
176 * @brief Get ProcessorSummary fields
177 *
178 * @param[in] aResp Shared pointer for completing asynchronous calls
179 * @param[in] service dbus service for Cpu Information
180 * @param[in] path dbus path for Cpu
181 *
182 * @return None.
183 */
184inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
185 const std::string& service,
186 const std::string& path)
187{
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800188 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500189 const bool cpuPresenceCheck) {
190 if (ec3)
191 {
192 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
193 return;
194 }
195 modifyCpuPresenceState(aResp, cpuPresenceCheck);
196 };
197
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500198 // Get the Presence of CPU
199 sdbusplus::asio::getProperty<bool>(
200 *crow::connections::systemBus, service, path,
201 "xyz.openbmc_project.Inventory.Item", "Present",
202 std::move(getCpuPresenceState));
203
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800204 auto getCpuFunctionalState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500205 const bool cpuFunctionalCheck) {
206 if (ec3)
207 {
208 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
209 return;
210 }
211 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
212 };
213
Ali Ahmed382d6472021-09-03 16:53:53 -0500214 // Get the Functional State
215 sdbusplus::asio::getProperty<bool>(
216 *crow::connections::systemBus, service, path,
217 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
218 std::move(getCpuFunctionalState));
219
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200220 sdbusplus::asio::getAllProperties(
221 *crow::connections::systemBus, service, path,
222 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500223 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800224 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800225 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700226 if (ec2)
227 {
228 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
229 messages::internalError(aResp->res);
230 return;
231 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500232 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200233 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500234}
235
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500236/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500237 * @brief processMemoryProperties fields
238 *
239 * @param[in] aResp Shared pointer for completing asynchronous calls
240 * @param[in] service dbus service for memory Information
241 * @param[in] path dbus path for Memory
242 * @param[in] DBUS properties for memory
243 *
244 * @return None.
245 */
246inline void
247 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
248 const std::string& service, const std::string& path,
249 const dbus::utility::DBusPropertiesMap& properties)
250{
251 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Dimm properties.";
252
253 if (properties.empty())
254 {
255 sdbusplus::asio::getProperty<bool>(
256 *crow::connections::systemBus, service, path,
257 "xyz.openbmc_project.State."
258 "Decorator.OperationalStatus",
259 "Functional",
260 [aResp](const boost::system::error_code& ec3, bool dimmState) {
261 if (ec3)
262 {
263 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
264 return;
265 }
266 updateDimmProperties(aResp, dimmState);
267 });
268 return;
269 }
270
271 const size_t* memorySizeInKB = nullptr;
272
273 const bool success = sdbusplus::unpackPropertiesNoThrow(
274 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
275 memorySizeInKB);
276
277 if (!success)
278 {
279 messages::internalError(aResp->res);
280 return;
281 }
282
283 if (memorySizeInKB != nullptr)
284 {
285 nlohmann::json& totalMemory =
286 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
287 const uint64_t* preValue = totalMemory.get_ptr<const uint64_t*>();
288 if (preValue == nullptr)
289 {
290 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
291 *memorySizeInKB / static_cast<size_t>(1024 * 1024);
292 }
293 else
294 {
295 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
296 *memorySizeInKB / static_cast<size_t>(1024 * 1024) + *preValue;
297 }
298 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] = "Enabled";
299 }
300}
301
302/*
303 * @brief Get getMemorySummary fields
304 *
305 * @param[in] aResp Shared pointer for completing asynchronous calls
306 * @param[in] service dbus service for memory Information
307 * @param[in] path dbus path for memory
308 *
309 * @return None.
310 */
311inline void getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
312 const std::string& service,
313 const std::string& path)
314{
315 sdbusplus::asio::getAllProperties(
316 *crow::connections::systemBus, service, path,
317 "xyz.openbmc_project.Inventory.Item.Dimm",
318 [aResp, service,
319 path](const boost::system::error_code& ec2,
320 const dbus::utility::DBusPropertiesMap& properties) {
321 if (ec2)
322 {
323 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
324 messages::internalError(aResp->res);
325 return;
326 }
327 processMemoryProperties(aResp, service, path, properties);
328 });
329}
330
331/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700332 * @brief Retrieves computer system properties over dbus
333 *
334 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500335 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700336 *
337 * @return None.
338 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700339inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800340 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700341 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700342{
Ed Tanous6c34de42018-08-29 13:37:36 -0700343 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800344 constexpr std::array<std::string_view, 5> interfaces = {
345 "xyz.openbmc_project.Inventory.Decorator.Asset",
346 "xyz.openbmc_project.Inventory.Item.Cpu",
347 "xyz.openbmc_project.Inventory.Item.Dimm",
348 "xyz.openbmc_project.Inventory.Item.System",
349 "xyz.openbmc_project.Common.UUID",
350 };
351 dbus::utility::getSubTree(
352 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800353 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800354 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800355 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700356 if (ec)
357 {
358 BMCWEB_LOG_DEBUG << "DBUS response error";
359 messages::internalError(aResp->res);
360 return;
361 }
362 // Iterate over all retrieved ObjectPaths.
363 for (const std::pair<
364 std::string,
365 std::vector<std::pair<std::string, std::vector<std::string>>>>&
366 object : subtree)
367 {
368 const std::string& path = object.first;
369 BMCWEB_LOG_DEBUG << "Got path: " << path;
370 const std::vector<std::pair<std::string, std::vector<std::string>>>&
371 connectionNames = object.second;
372 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700373 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700374 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700375 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700376
377 auto memoryHealth = std::make_shared<HealthPopulate>(
378 aResp, "/MemorySummary/Status"_json_pointer);
379
380 auto cpuHealth = std::make_shared<HealthPopulate>(
381 aResp, "/ProcessorSummary/Status"_json_pointer);
382
383 systemHealth->children.emplace_back(memoryHealth);
384 systemHealth->children.emplace_back(cpuHealth);
385
386 // This is not system, so check if it's cpu, dimm, UUID or
387 // BiosVer
388 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700389 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700390 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700391 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700392 if (interfaceName ==
393 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700394 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700395 BMCWEB_LOG_DEBUG
396 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500397
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500398 getMemorySummary(aResp, connection.first, path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700399
400 memoryHealth->inventory.emplace_back(path);
401 }
402 else if (interfaceName ==
403 "xyz.openbmc_project.Inventory.Item.Cpu")
404 {
405 BMCWEB_LOG_DEBUG
406 << "Found Cpu, now get its properties.";
407
408 getProcessorSummary(aResp, connection.first, path);
409
410 cpuHealth->inventory.emplace_back(path);
411 }
412 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
413 {
414 BMCWEB_LOG_DEBUG
415 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200416
417 sdbusplus::asio::getAllProperties(
418 *crow::connections::systemBus, connection.first,
419 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800420 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700421 const dbus::utility::DBusPropertiesMap&
422 properties) {
423 if (ec3)
424 {
425 BMCWEB_LOG_DEBUG << "DBUS response error "
426 << ec3;
427 messages::internalError(aResp->res);
428 return;
429 }
430 BMCWEB_LOG_DEBUG << "Got " << properties.size()
431 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700432
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200433 const std::string* uUID = nullptr;
434
435 const bool success =
436 sdbusplus::unpackPropertiesNoThrow(
437 dbus_utils::UnpackErrorPrinter(),
438 properties, "UUID", uUID);
439
440 if (!success)
441 {
442 messages::internalError(aResp->res);
443 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700444 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200445
446 if (uUID != nullptr)
447 {
448 std::string valueStr = *uUID;
449 if (valueStr.size() == 32)
450 {
451 valueStr.insert(8, 1, '-');
452 valueStr.insert(13, 1, '-');
453 valueStr.insert(18, 1, '-');
454 valueStr.insert(23, 1, '-');
455 }
456 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
457 aResp->res.jsonValue["UUID"] = valueStr;
458 }
459 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700460 }
461 else if (interfaceName ==
462 "xyz.openbmc_project.Inventory.Item.System")
463 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200464 sdbusplus::asio::getAllProperties(
465 *crow::connections::systemBus, connection.first,
466 path,
467 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800468 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700469 const dbus::utility::DBusPropertiesMap&
470 propertiesList) {
471 if (ec2)
472 {
473 // doesn't have to include this
474 // interface
475 return;
476 }
477 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
478 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200479
480 const std::string* partNumber = nullptr;
481 const std::string* serialNumber = nullptr;
482 const std::string* manufacturer = nullptr;
483 const std::string* model = nullptr;
484 const std::string* subModel = nullptr;
485
486 const bool success =
487 sdbusplus::unpackPropertiesNoThrow(
488 dbus_utils::UnpackErrorPrinter(),
489 propertiesList, "PartNumber", partNumber,
490 "SerialNumber", serialNumber,
491 "Manufacturer", manufacturer, "Model",
492 model, "SubModel", subModel);
493
494 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700495 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200496 messages::internalError(aResp->res);
497 return;
498 }
499
500 if (partNumber != nullptr)
501 {
502 aResp->res.jsonValue["PartNumber"] =
503 *partNumber;
504 }
505
506 if (serialNumber != nullptr)
507 {
508 aResp->res.jsonValue["SerialNumber"] =
509 *serialNumber;
510 }
511
512 if (manufacturer != nullptr)
513 {
514 aResp->res.jsonValue["Manufacturer"] =
515 *manufacturer;
516 }
517
518 if (model != nullptr)
519 {
520 aResp->res.jsonValue["Model"] = *model;
521 }
522
523 if (subModel != nullptr)
524 {
525 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700526 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500527
Ed Tanous002d39b2022-05-31 08:59:27 -0700528 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700529 sw_util::populateSoftwareInformation(
530 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700531 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200532 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700533
Ed Tanous002d39b2022-05-31 08:59:27 -0700534 sdbusplus::asio::getProperty<std::string>(
535 *crow::connections::systemBus, connection.first,
536 path,
537 "xyz.openbmc_project.Inventory.Decorator."
538 "AssetTag",
539 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800540 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700541 const std::string& value) {
542 if (ec2)
543 {
544 // doesn't have to include this
545 // interface
546 return;
547 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700548
Ed Tanous002d39b2022-05-31 08:59:27 -0700549 aResp->res.jsonValue["AssetTag"] = value;
550 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700551 }
552 }
553 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700554 }
Ed Tanous66173382018-08-15 18:20:59 -0700555 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700556}
557
558/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700559 * @brief Retrieves host state properties over dbus
560 *
561 * @param[in] aResp Shared pointer for completing asynchronous calls.
562 *
563 * @return None.
564 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800565inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700566{
567 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700568 sdbusplus::asio::getProperty<std::string>(
569 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
570 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
571 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800572 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700573 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700574 if (ec)
575 {
576 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700577 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700578 // Service not available, no error, just don't return
579 // host state info
580 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700581 return;
582 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700583 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
584 messages::internalError(aResp->res);
585 return;
586 }
Ed Tanous66173382018-08-15 18:20:59 -0700587
Ed Tanous002d39b2022-05-31 08:59:27 -0700588 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
589 // Verify Host State
590 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
591 {
592 aResp->res.jsonValue["PowerState"] = "On";
593 aResp->res.jsonValue["Status"]["State"] = "Enabled";
594 }
595 else if (hostState ==
596 "xyz.openbmc_project.State.Host.HostState.Quiesced")
597 {
598 aResp->res.jsonValue["PowerState"] = "On";
599 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
600 }
601 else if (hostState ==
602 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
603 {
604 aResp->res.jsonValue["PowerState"] = "On";
605 aResp->res.jsonValue["Status"]["State"] = "InTest";
606 }
607 else if (
608 hostState ==
609 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
610 {
611 aResp->res.jsonValue["PowerState"] = "PoweringOn";
612 aResp->res.jsonValue["Status"]["State"] = "Starting";
613 }
614 else if (hostState ==
615 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
616 {
617 aResp->res.jsonValue["PowerState"] = "PoweringOff";
618 aResp->res.jsonValue["Status"]["State"] = "Disabled";
619 }
620 else
621 {
622 aResp->res.jsonValue["PowerState"] = "Off";
623 aResp->res.jsonValue["Status"]["State"] = "Disabled";
624 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700625 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700626}
627
628/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500629 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 *
631 * @param[in] dbusSource The boot source in DBUS speak.
632 *
633 * @return Returns as a string, the boot source in Redfish terms. If translation
634 * cannot be done, returns an empty string.
635 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000636inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530637{
638 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
639 {
640 return "None";
641 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700642 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530643 {
644 return "Hdd";
645 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700646 if (dbusSource ==
647 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530648 {
649 return "Cd";
650 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700651 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530652 {
653 return "Pxe";
654 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700655 if (dbusSource ==
656 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700657 {
658 return "Usb";
659 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700660 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661}
662
663/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300664 * @brief Translates boot type DBUS property value to redfish.
665 *
666 * @param[in] dbusType The boot type in DBUS speak.
667 *
668 * @return Returns as a string, the boot type in Redfish terms. If translation
669 * cannot be done, returns an empty string.
670 */
671inline std::string dbusToRfBootType(const std::string& dbusType)
672{
673 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
674 {
675 return "Legacy";
676 }
677 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
678 {
679 return "UEFI";
680 }
681 return "";
682}
683
684/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500685 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686 *
687 * @param[in] dbusMode The boot mode in DBUS speak.
688 *
689 * @return Returns as a string, the boot mode in Redfish terms. If translation
690 * cannot be done, returns an empty string.
691 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000692inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530693{
694 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
695 {
696 return "None";
697 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700698 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530699 {
700 return "Diags";
701 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700702 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530703 {
704 return "BiosSetup";
705 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700706 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530707}
708
709/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600710 * @brief Translates boot progress DBUS property value to redfish.
711 *
712 * @param[in] dbusBootProgress The boot progress in DBUS speak.
713 *
714 * @return Returns as a string, the boot progress in Redfish terms. If
715 * translation cannot be done, returns "None".
716 */
717inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
718{
719 // Now convert the D-Bus BootProgress to the appropriate Redfish
720 // enum
721 std::string rfBpLastState = "None";
722 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
723 "ProgressStages.Unspecified")
724 {
725 rfBpLastState = "None";
726 }
727 else if (dbusBootProgress ==
728 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
729 "PrimaryProcInit")
730 {
731 rfBpLastState = "PrimaryProcessorInitializationStarted";
732 }
733 else if (dbusBootProgress ==
734 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
735 "BusInit")
736 {
737 rfBpLastState = "BusInitializationStarted";
738 }
739 else if (dbusBootProgress ==
740 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
741 "MemoryInit")
742 {
743 rfBpLastState = "MemoryInitializationStarted";
744 }
745 else if (dbusBootProgress ==
746 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
747 "SecondaryProcInit")
748 {
749 rfBpLastState = "SecondaryProcessorInitializationStarted";
750 }
751 else if (dbusBootProgress ==
752 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
753 "PCIInit")
754 {
755 rfBpLastState = "PCIResourceConfigStarted";
756 }
757 else if (dbusBootProgress ==
758 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
759 "SystemSetup")
760 {
761 rfBpLastState = "SetupEntered";
762 }
763 else if (dbusBootProgress ==
764 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
765 "SystemInitComplete")
766 {
767 rfBpLastState = "SystemHardwareInitializationComplete";
768 }
769 else if (dbusBootProgress ==
770 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
771 "OSStart")
772 {
773 rfBpLastState = "OSBootStarted";
774 }
775 else if (dbusBootProgress ==
776 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
777 "OSRunning")
778 {
779 rfBpLastState = "OSRunning";
780 }
781 else
782 {
783 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
784 << dbusBootProgress;
785 // Just return the default
786 }
787 return rfBpLastState;
788}
789
790/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500791 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530792 *
793 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 * @param[out] bootSource The DBus source
795 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530796 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700797 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530798 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800799inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500800 const std::string& rfSource,
801 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530802{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300803 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
804 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700805
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530806 if (rfSource == "None")
807 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700808 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530809 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700810 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530811 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700812 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
813 }
814 else if (rfSource == "Hdd")
815 {
816 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
817 }
818 else if (rfSource == "Diags")
819 {
820 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
821 }
822 else if (rfSource == "Cd")
823 {
824 bootSource =
825 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
826 }
827 else if (rfSource == "BiosSetup")
828 {
829 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530830 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700831 else if (rfSource == "Usb")
832 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700833 bootSource =
834 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700835 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530836 else
837 {
George Liu0fda0f12021-11-16 10:06:17 +0800838 BMCWEB_LOG_DEBUG
839 << "Invalid property value for BootSourceOverrideTarget: "
840 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700841 messages::propertyValueNotInList(aResp->res, rfSource,
842 "BootSourceTargetOverride");
843 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530844 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700845 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530846}
Ali Ahmed19817712021-06-29 17:01:52 -0500847
Andrew Geissler978b8802020-11-19 13:36:40 -0600848/**
849 * @brief Retrieves boot progress of the system
850 *
851 * @param[in] aResp Shared pointer for generating response message.
852 *
853 * @return None.
854 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800855inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600856{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700857 sdbusplus::asio::getProperty<std::string>(
858 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
859 "/xyz/openbmc_project/state/host0",
860 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800861 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700862 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700863 if (ec)
864 {
865 // BootProgress is an optional object so just do nothing if
866 // not found
867 return;
868 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600869
Ed Tanous002d39b2022-05-31 08:59:27 -0700870 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600871
Ed Tanous002d39b2022-05-31 08:59:27 -0700872 aResp->res.jsonValue["BootProgress"]["LastState"] =
873 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700874 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600875}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530876
877/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000878 * @brief Retrieves boot progress Last Update of the system
879 *
880 * @param[in] aResp Shared pointer for generating response message.
881 *
882 * @return None.
883 */
884inline void getBootProgressLastStateTime(
885 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
886{
887 sdbusplus::asio::getProperty<uint64_t>(
888 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
889 "/xyz/openbmc_project/state/host0",
890 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800891 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000892 const uint64_t lastStateTime) {
893 if (ec)
894 {
895 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
896 return;
897 }
898
899 // BootProgressLastUpdate is the last time the BootProgress property
900 // was updated. The time is the Epoch time, number of microseconds
901 // since 1 Jan 1970 00::00::00 UTC."
902 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
903 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
904
905 // Convert to ISO 8601 standard
906 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
907 redfish::time_utils::getDateTimeUintUs(lastStateTime);
908 });
909}
910
911/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300912 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300913 *
914 * @param[in] aResp Shared pointer for generating response message.
915 *
916 * @return None.
917 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300919inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300920{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700921 sdbusplus::asio::getProperty<std::string>(
922 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
923 "/xyz/openbmc_project/control/host0/boot",
924 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800925 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700926 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700927 if (ec)
928 {
929 // not an error, don't have to have the interface
930 return;
931 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300932
Ed Tanous002d39b2022-05-31 08:59:27 -0700933 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300934
Ed Tanous002d39b2022-05-31 08:59:27 -0700935 aResp->res.jsonValue["Boot"]
936 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700937 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300938
Ed Tanous002d39b2022-05-31 08:59:27 -0700939 auto rfType = dbusToRfBootType(bootType);
940 if (rfType.empty())
941 {
942 messages::internalError(aResp->res);
943 return;
944 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300945
Ed Tanous002d39b2022-05-31 08:59:27 -0700946 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700947 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300948}
949
950/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300951 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530952 *
953 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530954 *
955 * @return None.
956 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300957
958inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700960 sdbusplus::asio::getProperty<std::string>(
961 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
962 "/xyz/openbmc_project/control/host0/boot",
963 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800964 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700965 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700966 if (ec)
967 {
968 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
969 messages::internalError(aResp->res);
970 return;
971 }
972
973 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
974
975 aResp->res
976 .jsonValue["Boot"]
977 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
978 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
979
980 if (bootModeStr !=
981 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
982 {
983 auto rfMode = dbusToRfBootMode(bootModeStr);
984 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700986 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
987 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530988 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700989 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700990 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530991}
992
993/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300994 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530995 *
996 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530997 *
998 * @return None.
999 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001000
1001inline void
1002 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301003{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001004 sdbusplus::asio::getProperty<std::string>(
1005 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1006 "/xyz/openbmc_project/control/host0/boot",
1007 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001008 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001009 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001010 if (ec)
1011 {
1012 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001013 if (ec.value() == boost::asio::error::host_unreachable)
1014 {
1015 return;
1016 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001017 messages::internalError(aResp->res);
1018 return;
1019 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301020
Ed Tanous002d39b2022-05-31 08:59:27 -07001021 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022
Ed Tanous002d39b2022-05-31 08:59:27 -07001023 auto rfSource = dbusToRfBootSource(bootSourceStr);
1024 if (!rfSource.empty())
1025 {
1026 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1027 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001028
Ed Tanous002d39b2022-05-31 08:59:27 -07001029 // Get BootMode as BootSourceOverrideTarget is constructed
1030 // from both BootSource and BootMode
1031 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001032 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301033}
1034
1035/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001036 * @brief This functions abstracts all the logic behind getting a
1037 * "BootSourceOverrideEnabled" property from an overall boot override enable
1038 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301039 *
1040 * @param[in] aResp Shared pointer for generating response message.
1041 *
1042 * @return None.
1043 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001045inline void
1046 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1047 const bool bootOverrideEnableSetting)
1048{
1049 if (!bootOverrideEnableSetting)
1050 {
1051 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1052 return;
1053 }
1054
1055 // If boot source override is enabled, we need to check 'one_time'
1056 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001057 sdbusplus::asio::getProperty<bool>(
1058 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1059 "/xyz/openbmc_project/control/host0/boot/one_time",
1060 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001061 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001062 if (ec)
1063 {
1064 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1065 messages::internalError(aResp->res);
1066 return;
1067 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301068
Ed Tanous002d39b2022-05-31 08:59:27 -07001069 if (oneTimeSetting)
1070 {
1071 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1072 }
1073 else
1074 {
1075 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1076 "Continuous";
1077 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001078 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301079}
1080
1081/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001082 * @brief Retrieves boot override enable over DBUS
1083 *
1084 * @param[in] aResp Shared pointer for generating response message.
1085 *
1086 * @return None.
1087 */
1088
1089inline void
1090 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1091{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001092 sdbusplus::asio::getProperty<bool>(
1093 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1094 "/xyz/openbmc_project/control/host0/boot",
1095 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001096 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001097 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001098 if (ec)
1099 {
1100 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001101 if (ec.value() == boost::asio::error::host_unreachable)
1102 {
1103 return;
1104 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001105 messages::internalError(aResp->res);
1106 return;
1107 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001108
Ed Tanous002d39b2022-05-31 08:59:27 -07001109 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001110 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001111}
1112
1113/**
1114 * @brief Retrieves boot source override properties
1115 *
1116 * @param[in] aResp Shared pointer for generating response message.
1117 *
1118 * @return None.
1119 */
1120inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1121{
1122 BMCWEB_LOG_DEBUG << "Get boot information.";
1123
1124 getBootOverrideSource(aResp);
1125 getBootOverrideType(aResp);
1126 getBootOverrideEnable(aResp);
1127}
1128
1129/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001130 * @brief Retrieves the Last Reset Time
1131 *
1132 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1133 * and power off. Even though this is the "system" Redfish object look at the
1134 * chassis D-Bus interface for the LastStateChangeTime since this has the
1135 * last power operation time.
1136 *
1137 * @param[in] aResp Shared pointer for generating response message.
1138 *
1139 * @return None.
1140 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001141inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001142{
1143 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1144
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001145 sdbusplus::asio::getProperty<uint64_t>(
1146 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1147 "/xyz/openbmc_project/state/chassis0",
1148 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001149 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001150 if (ec)
1151 {
1152 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1153 return;
1154 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001155
Ed Tanous002d39b2022-05-31 08:59:27 -07001156 // LastStateChangeTime is epoch time, in milliseconds
1157 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1158 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001159
Ed Tanous002d39b2022-05-31 08:59:27 -07001160 // Convert to ISO 8601 standard
1161 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001162 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001163 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001164}
1165
1166/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001167 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1168 *
1169 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1170 * corresponding property "AttemptsLeft" that keeps track of the amount of
1171 * automatic retry attempts left are hosted in phosphor-state-manager through
1172 * dbus.
1173 *
1174 * @param[in] aResp Shared pointer for generating response message.
1175 *
1176 * @return None.
1177 */
1178inline void
1179 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1180{
1181 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1182
1183 sdbusplus::asio::getAllProperties(
1184 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1185 "/xyz/openbmc_project/state/host0",
1186 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1187 [aResp{aResp}](const boost::system::error_code& ec,
1188 const dbus::utility::DBusPropertiesMap& propertiesList) {
1189 if (ec)
1190 {
1191 if (ec.value() != EBADR)
1192 {
1193 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1194 messages::internalError(aResp->res);
1195 }
1196 return;
1197 }
1198
1199 const uint32_t* attemptsLeft = nullptr;
1200 const uint32_t* retryAttempts = nullptr;
1201
1202 const bool success = sdbusplus::unpackPropertiesNoThrow(
1203 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1204 attemptsLeft, "RetryAttempts", retryAttempts);
1205
1206 if (!success)
1207 {
1208 messages::internalError(aResp->res);
1209 return;
1210 }
1211
1212 if (attemptsLeft != nullptr)
1213 {
1214 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1215 *attemptsLeft;
1216 }
1217
1218 if (retryAttempts != nullptr)
1219 {
1220 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1221 *retryAttempts;
1222 }
1223 });
1224}
1225
1226/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001227 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1228 *
1229 * @param[in] aResp Shared pointer for generating response message.
1230 *
1231 * @return None.
1232 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001233inline void
1234 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001235{
1236 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1237
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001238 sdbusplus::asio::getProperty<bool>(
1239 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1240 "/xyz/openbmc_project/control/host0/auto_reboot",
1241 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001242 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001243 if (ec)
1244 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001245 if (ec.value() != EBADR)
1246 {
1247 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1248 messages::internalError(aResp->res);
1249 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001250 return;
1251 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001252
Ed Tanous002d39b2022-05-31 08:59:27 -07001253 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1254 if (autoRebootEnabled)
1255 {
1256 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1257 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001258 }
1259 else
1260 {
1261 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1262 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001263 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001264
Ed Tanous002d39b2022-05-31 08:59:27 -07001265 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1266 // and RetryAttempts. OpenBMC only supports Disabled and
1267 // RetryAttempts.
1268 aResp->res.jsonValue["Boot"]
1269 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1270 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001271 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001272}
1273
1274/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001275 * @brief Sets RetryAttempts
1276 *
1277 * @param[in] aResp Shared pointer for generating response message.
1278 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1279 *
1280 *@return None.
1281 */
1282
1283inline void
1284 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1285 const uint32_t retryAttempts)
1286{
1287 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1288 crow::connections::systemBus->async_method_call(
1289 [aResp](const boost::system::error_code& ec) {
1290 if (ec)
1291 {
1292 BMCWEB_LOG_ERROR
1293 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1294 messages::internalError(aResp->res);
1295 return;
1296 }
1297 },
1298 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1299 "org.freedesktop.DBus.Properties", "Set",
1300 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1301 std::variant<uint32_t>(retryAttempts));
1302}
1303
1304/**
George Liuc6a620f2020-04-10 17:18:11 +08001305 * @brief Retrieves power restore policy over DBUS.
1306 *
1307 * @param[in] aResp Shared pointer for generating response message.
1308 *
1309 * @return None.
1310 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001311inline void
1312 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001313{
1314 BMCWEB_LOG_DEBUG << "Get power restore policy";
1315
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001316 sdbusplus::asio::getProperty<std::string>(
1317 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1318 "/xyz/openbmc_project/control/host0/power_restore_policy",
1319 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001320 [aResp](const boost::system::error_code& ec,
1321 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001322 if (ec)
1323 {
1324 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1325 return;
1326 }
George Liuc6a620f2020-04-10 17:18:11 +08001327
Ed Tanous002d39b2022-05-31 08:59:27 -07001328 const boost::container::flat_map<std::string, std::string> policyMaps = {
1329 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1330 "AlwaysOn"},
1331 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1332 "AlwaysOff"},
1333 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1334 "LastState"},
1335 // Return `AlwaysOff` when power restore policy set to "None"
1336 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1337 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001338
Ed Tanous002d39b2022-05-31 08:59:27 -07001339 auto policyMapsIt = policyMaps.find(policy);
1340 if (policyMapsIt == policyMaps.end())
1341 {
1342 messages::internalError(aResp->res);
1343 return;
1344 }
George Liuc6a620f2020-04-10 17:18:11 +08001345
Ed Tanous002d39b2022-05-31 08:59:27 -07001346 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001347 });
George Liuc6a620f2020-04-10 17:18:11 +08001348}
1349
1350/**
Ali Ahmed19817712021-06-29 17:01:52 -05001351 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1352 * TPM is required for booting the host.
1353 *
1354 * @param[in] aResp Shared pointer for generating response message.
1355 *
1356 * @return None.
1357 */
1358inline void getTrustedModuleRequiredToBoot(
1359 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1360{
1361 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001362 constexpr std::array<std::string_view, 1> interfaces = {
1363 "xyz.openbmc_project.Control.TPM.Policy"};
1364 dbus::utility::getSubTree(
1365 "/", 0, interfaces,
1366 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001367 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001368 if (ec)
1369 {
1370 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1371 << ec;
1372 // This is an optional D-Bus object so just return if
1373 // error occurs
1374 return;
1375 }
1376 if (subtree.empty())
1377 {
1378 // As noted above, this is an optional interface so just return
1379 // if there is no instance found
1380 return;
1381 }
1382
1383 /* When there is more than one TPMEnable object... */
1384 if (subtree.size() > 1)
1385 {
1386 BMCWEB_LOG_DEBUG
1387 << "DBUS response has more than 1 TPM Enable object:"
1388 << subtree.size();
1389 // Throw an internal Error and return
1390 messages::internalError(aResp->res);
1391 return;
1392 }
1393
1394 // Make sure the Dbus response map has a service and objectPath
1395 // field
1396 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1397 {
1398 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1399 messages::internalError(aResp->res);
1400 return;
1401 }
1402
1403 const std::string& path = subtree[0].first;
1404 const std::string& serv = subtree[0].second.begin()->first;
1405
1406 // Valid TPM Enable object found, now reading the current value
1407 sdbusplus::asio::getProperty<bool>(
1408 *crow::connections::systemBus, serv, path,
1409 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001410 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001411 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001412 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001413 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001414 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001415 messages::internalError(aResp->res);
1416 return;
1417 }
1418
Ed Tanous002d39b2022-05-31 08:59:27 -07001419 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001420 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001421 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1422 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001423 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001424 else
1425 {
1426 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1427 "Disabled";
1428 }
1429 });
George Liue99073f2022-12-09 11:06:16 +08001430 });
Ali Ahmed19817712021-06-29 17:01:52 -05001431}
1432
1433/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001434 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1435 * TPM is required for booting the host.
1436 *
1437 * @param[in] aResp Shared pointer for generating response message.
1438 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1439 *
1440 * @return None.
1441 */
1442inline void setTrustedModuleRequiredToBoot(
1443 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1444{
1445 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001446 constexpr std::array<std::string_view, 1> interfaces = {
1447 "xyz.openbmc_project.Control.TPM.Policy"};
1448 dbus::utility::getSubTree(
1449 "/", 0, interfaces,
1450 [aResp,
1451 tpmRequired](const boost::system::error_code& ec,
1452 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001453 if (ec)
1454 {
1455 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1456 << ec;
1457 messages::internalError(aResp->res);
1458 return;
1459 }
1460 if (subtree.empty())
1461 {
1462 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1463 "TrustedModuleRequiredToBoot");
1464 return;
1465 }
1466
1467 /* When there is more than one TPMEnable object... */
1468 if (subtree.size() > 1)
1469 {
1470 BMCWEB_LOG_DEBUG
1471 << "DBUS response has more than 1 TPM Enable object:"
1472 << subtree.size();
1473 // Throw an internal Error and return
1474 messages::internalError(aResp->res);
1475 return;
1476 }
1477
1478 // Make sure the Dbus response map has a service and objectPath
1479 // field
1480 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1481 {
1482 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1483 messages::internalError(aResp->res);
1484 return;
1485 }
1486
1487 const std::string& path = subtree[0].first;
1488 const std::string& serv = subtree[0].second.begin()->first;
1489
1490 if (serv.empty())
1491 {
1492 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1493 messages::internalError(aResp->res);
1494 return;
1495 }
1496
1497 // Valid TPM Enable object found, now setting the value
1498 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001499 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001500 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001501 {
1502 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001503 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001504 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001505 messages::internalError(aResp->res);
1506 return;
1507 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001508 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1509 },
1510 serv, path, "org.freedesktop.DBus.Properties", "Set",
1511 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1512 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001513 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001514}
1515
1516/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301517 * @brief Sets boot properties into DBUS object(s).
1518 *
1519 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001520 * @param[in] bootType The boot type to set.
1521 * @return Integer error code.
1522 */
1523inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001524 const std::optional<std::string>& bootType)
1525{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001526 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001527
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001528 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001529 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001530 return;
1531 }
1532
1533 // Source target specified
1534 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1535 // Figure out which DBUS interface and property to use
1536 if (*bootType == "Legacy")
1537 {
1538 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1539 }
1540 else if (*bootType == "UEFI")
1541 {
1542 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1543 }
1544 else
1545 {
1546 BMCWEB_LOG_DEBUG << "Invalid property value for "
1547 "BootSourceOverrideMode: "
1548 << *bootType;
1549 messages::propertyValueNotInList(aResp->res, *bootType,
1550 "BootSourceOverrideMode");
1551 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001552 }
1553
1554 // Act on validated parameters
1555 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1556
1557 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001558 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001559 if (ec)
1560 {
1561 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1562 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001563 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001564 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001565 return;
1566 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001567 messages::internalError(aResp->res);
1568 return;
1569 }
1570 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001571 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001572 "xyz.openbmc_project.Settings",
1573 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001574 "org.freedesktop.DBus.Properties", "Set",
1575 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001576 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001577}
1578
1579/**
1580 * @brief Sets boot properties into DBUS object(s).
1581 *
1582 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001583 * @param[in] bootType The boot type to set.
1584 * @return Integer error code.
1585 */
1586inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1587 const std::optional<std::string>& bootEnable)
1588{
1589 if (!bootEnable)
1590 {
1591 return;
1592 }
1593 // Source target specified
1594 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1595
1596 bool bootOverrideEnable = false;
1597 bool bootOverridePersistent = false;
1598 // Figure out which DBUS interface and property to use
1599 if (*bootEnable == "Disabled")
1600 {
1601 bootOverrideEnable = false;
1602 }
1603 else if (*bootEnable == "Once")
1604 {
1605 bootOverrideEnable = true;
1606 bootOverridePersistent = false;
1607 }
1608 else if (*bootEnable == "Continuous")
1609 {
1610 bootOverrideEnable = true;
1611 bootOverridePersistent = true;
1612 }
1613 else
1614 {
George Liu0fda0f12021-11-16 10:06:17 +08001615 BMCWEB_LOG_DEBUG
1616 << "Invalid property value for BootSourceOverrideEnabled: "
1617 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001618 messages::propertyValueNotInList(aResp->res, *bootEnable,
1619 "BootSourceOverrideEnabled");
1620 return;
1621 }
1622
1623 // Act on validated parameters
1624 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1625
1626 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001627 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001628 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001629 {
Ed Tanous8a592812022-06-04 09:06:59 -07001630 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001631 messages::internalError(aResp->res);
1632 return;
1633 }
1634 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001635 },
1636 "xyz.openbmc_project.Settings",
1637 "/xyz/openbmc_project/control/host0/boot",
1638 "org.freedesktop.DBus.Properties", "Set",
1639 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001640 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001641
1642 if (!bootOverrideEnable)
1643 {
1644 return;
1645 }
1646
1647 // In case boot override is enabled we need to set correct value for the
1648 // 'one_time' enable DBus interface
1649 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1650 << bootOverridePersistent;
1651
1652 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001653 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001654 if (ec)
1655 {
1656 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1657 messages::internalError(aResp->res);
1658 return;
1659 }
1660 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001661 },
1662 "xyz.openbmc_project.Settings",
1663 "/xyz/openbmc_project/control/host0/boot/one_time",
1664 "org.freedesktop.DBus.Properties", "Set",
1665 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001666 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001667}
1668
1669/**
1670 * @brief Sets boot properties into DBUS object(s).
1671 *
1672 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301673 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301674 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001675 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301676 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001677inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001678 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301679{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001680 std::string bootSourceStr;
1681 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001682
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001683 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301684 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001685 return;
1686 }
1687
1688 // Source target specified
1689 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1690 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001691 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1692 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001693 {
1694 BMCWEB_LOG_DEBUG
1695 << "Invalid property value for BootSourceOverrideTarget: "
1696 << *bootSource;
1697 messages::propertyValueNotInList(aResp->res, *bootSource,
1698 "BootSourceTargetOverride");
1699 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001700 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301701
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001702 // Act on validated parameters
1703 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1704 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001705
1706 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001707 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001708 if (ec)
1709 {
1710 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1711 messages::internalError(aResp->res);
1712 return;
1713 }
1714 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001715 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001716 "xyz.openbmc_project.Settings",
1717 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001718 "org.freedesktop.DBus.Properties", "Set",
1719 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001720 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001721
1722 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001723 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001724 if (ec)
1725 {
1726 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1727 messages::internalError(aResp->res);
1728 return;
1729 }
1730 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001731 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001732 "xyz.openbmc_project.Settings",
1733 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001734 "org.freedesktop.DBus.Properties", "Set",
1735 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001736 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001737}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001738
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001739/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001740 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301741 *
1742 * @param[in] aResp Shared pointer for generating response message.
1743 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001744 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301745 * @param[in] bootEnable The boot override enable from incoming RF request.
1746 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001747 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301748 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001749
1750inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1751 const std::optional<std::string>& bootSource,
1752 const std::optional<std::string>& bootType,
1753 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301754{
1755 BMCWEB_LOG_DEBUG << "Set boot information.";
1756
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001757 setBootModeOrSource(aResp, bootSource);
1758 setBootType(aResp, bootType);
1759 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301760}
1761
George Liuc6a620f2020-04-10 17:18:11 +08001762/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001763 * @brief Sets AssetTag
1764 *
1765 * @param[in] aResp Shared pointer for generating response message.
1766 * @param[in] assetTag "AssetTag" from request.
1767 *
1768 * @return None.
1769 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001770inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001771 const std::string& assetTag)
1772{
George Liue99073f2022-12-09 11:06:16 +08001773 constexpr std::array<std::string_view, 1> interfaces = {
1774 "xyz.openbmc_project.Inventory.Item.System"};
1775 dbus::utility::getSubTree(
1776 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001777 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001778 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001779 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001780 if (ec)
1781 {
1782 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1783 messages::internalError(aResp->res);
1784 return;
1785 }
1786 if (subtree.empty())
1787 {
1788 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1789 messages::internalError(aResp->res);
1790 return;
1791 }
1792 // Assume only 1 system D-Bus object
1793 // Throw an error if there is more than 1
1794 if (subtree.size() > 1)
1795 {
1796 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1797 messages::internalError(aResp->res);
1798 return;
1799 }
1800 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1801 {
1802 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1803 messages::internalError(aResp->res);
1804 return;
1805 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001806
Ed Tanous002d39b2022-05-31 08:59:27 -07001807 const std::string& path = subtree[0].first;
1808 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001809
Ed Tanous002d39b2022-05-31 08:59:27 -07001810 if (service.empty())
1811 {
1812 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1813 messages::internalError(aResp->res);
1814 return;
1815 }
1816
1817 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001818 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001819 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001820 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001821 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1822 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001823 messages::internalError(aResp->res);
1824 return;
1825 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001826 },
1827 service, path, "org.freedesktop.DBus.Properties", "Set",
1828 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1829 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001830 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001831}
1832
1833/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001834 * @brief Sets automaticRetry (Auto Reboot)
1835 *
1836 * @param[in] aResp Shared pointer for generating response message.
1837 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1838 *
1839 * @return None.
1840 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001841inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001842 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001843{
1844 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1845
1846 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001847 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001848
1849 if (automaticRetryConfig == "Disabled")
1850 {
1851 autoRebootEnabled = false;
1852 }
1853 else if (automaticRetryConfig == "RetryAttempts")
1854 {
1855 autoRebootEnabled = true;
1856 }
1857 else
1858 {
George Liu0fda0f12021-11-16 10:06:17 +08001859 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001860 << automaticRetryConfig;
1861 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1862 "AutomaticRetryConfig");
1863 return;
1864 }
1865
1866 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001867 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001868 if (ec)
1869 {
1870 messages::internalError(aResp->res);
1871 return;
1872 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001873 },
1874 "xyz.openbmc_project.Settings",
1875 "/xyz/openbmc_project/control/host0/auto_reboot",
1876 "org.freedesktop.DBus.Properties", "Set",
1877 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001878 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001879}
1880
1881/**
George Liuc6a620f2020-04-10 17:18:11 +08001882 * @brief Sets power restore policy properties.
1883 *
1884 * @param[in] aResp Shared pointer for generating response message.
1885 * @param[in] policy power restore policy properties from request.
1886 *
1887 * @return None.
1888 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001889inline void
1890 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1891 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001892{
1893 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1894
1895 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001896 {"AlwaysOn",
1897 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1898 {"AlwaysOff",
1899 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1900 {"LastState",
1901 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001902
1903 std::string powerRestorPolicy;
1904
Gunnar Mills4e69c902021-01-05 19:50:11 -06001905 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001906 if (policyMapsIt == policyMaps.end())
1907 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001908 messages::propertyValueNotInList(aResp->res, policy,
1909 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001910 return;
1911 }
1912
1913 powerRestorPolicy = policyMapsIt->second;
1914
1915 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001916 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001917 if (ec)
1918 {
1919 messages::internalError(aResp->res);
1920 return;
1921 }
George Liuc6a620f2020-04-10 17:18:11 +08001922 },
1923 "xyz.openbmc_project.Settings",
1924 "/xyz/openbmc_project/control/host0/power_restore_policy",
1925 "org.freedesktop.DBus.Properties", "Set",
1926 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001927 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001928}
1929
AppaRao Pulia6349912019-10-18 17:16:08 +05301930#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1931/**
1932 * @brief Retrieves provisioning status
1933 *
1934 * @param[in] aResp Shared pointer for completing asynchronous calls.
1935 *
1936 * @return None.
1937 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001938inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301939{
1940 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001941 sdbusplus::asio::getAllProperties(
1942 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1943 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001944 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001945 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001946 nlohmann::json& oemPFR =
1947 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1948 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1949 "#OemComputerSystem.OpenBmc";
1950 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001951
Ed Tanous002d39b2022-05-31 08:59:27 -07001952 if (ec)
1953 {
1954 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1955 // not an error, don't have to have the interface
1956 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1957 return;
1958 }
1959
1960 const bool* provState = nullptr;
1961 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001962
1963 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001964 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1965 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001966
1967 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001968 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001969 messages::internalError(aResp->res);
1970 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001971 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301972
Ed Tanous002d39b2022-05-31 08:59:27 -07001973 if ((provState == nullptr) || (lockState == nullptr))
1974 {
1975 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1976 messages::internalError(aResp->res);
1977 return;
1978 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301979
Ed Tanous002d39b2022-05-31 08:59:27 -07001980 if (*provState == true)
1981 {
1982 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301983 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001984 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301985 }
1986 else
1987 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001988 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301989 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001990 }
1991 else
1992 {
1993 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1994 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001995 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301996}
1997#endif
1998
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301999/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002000 * @brief Translate the PowerMode to a response message.
2001 *
2002 * @param[in] aResp Shared pointer for generating response message.
2003 * @param[in] modeValue PowerMode value to be translated
2004 *
2005 * @return None.
2006 */
2007inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2008 const std::string& modeValue)
2009{
George Liu0fda0f12021-11-16 10:06:17 +08002010 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002011 {
2012 aResp->res.jsonValue["PowerMode"] = "Static";
2013 }
George Liu0fda0f12021-11-16 10:06:17 +08002014 else if (
2015 modeValue ==
2016 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002017 {
2018 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2019 }
George Liu0fda0f12021-11-16 10:06:17 +08002020 else if (modeValue ==
2021 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002022 {
2023 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2024 }
George Liu0fda0f12021-11-16 10:06:17 +08002025 else if (modeValue ==
2026 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002027 {
2028 aResp->res.jsonValue["PowerMode"] = "OEM";
2029 }
2030 else
2031 {
2032 // Any other values would be invalid
2033 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2034 messages::internalError(aResp->res);
2035 }
2036}
2037
2038/**
2039 * @brief Retrieves system power mode
2040 *
2041 * @param[in] aResp Shared pointer for generating response message.
2042 *
2043 * @return None.
2044 */
2045inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2046{
2047 BMCWEB_LOG_DEBUG << "Get power mode.";
2048
2049 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002050 constexpr std::array<std::string_view, 1> interfaces = {
2051 "xyz.openbmc_project.Control.Power.Mode"};
2052 dbus::utility::getSubTree(
2053 "/", 0, interfaces,
2054 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002055 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002056 if (ec)
2057 {
2058 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2059 << ec;
2060 // This is an optional D-Bus object so just return if
2061 // error occurs
2062 return;
2063 }
2064 if (subtree.empty())
2065 {
2066 // As noted above, this is an optional interface so just return
2067 // if there is no instance found
2068 return;
2069 }
2070 if (subtree.size() > 1)
2071 {
2072 // More then one PowerMode object is not supported and is an
2073 // error
2074 BMCWEB_LOG_DEBUG
2075 << "Found more than 1 system D-Bus Power.Mode objects: "
2076 << subtree.size();
2077 messages::internalError(aResp->res);
2078 return;
2079 }
2080 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2081 {
2082 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2083 messages::internalError(aResp->res);
2084 return;
2085 }
2086 const std::string& path = subtree[0].first;
2087 const std::string& service = subtree[0].second.begin()->first;
2088 if (service.empty())
2089 {
2090 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2091 messages::internalError(aResp->res);
2092 return;
2093 }
2094 // Valid Power Mode object found, now read the current value
2095 sdbusplus::asio::getProperty<std::string>(
2096 *crow::connections::systemBus, service, path,
2097 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002098 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002099 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002100 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002101 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002102 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002103 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002104 messages::internalError(aResp->res);
2105 return;
2106 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002107
Ed Tanous002d39b2022-05-31 08:59:27 -07002108 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2109 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002110
Ed Tanous002d39b2022-05-31 08:59:27 -07002111 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2112 translatePowerMode(aResp, pmode);
2113 });
George Liue99073f2022-12-09 11:06:16 +08002114 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002115}
2116
2117/**
2118 * @brief Validate the specified mode is valid and return the PowerMode
2119 * name associated with that string
2120 *
2121 * @param[in] aResp Shared pointer for generating response message.
2122 * @param[in] modeString String representing the desired PowerMode
2123 *
2124 * @return PowerMode value or empty string if mode is not valid
2125 */
2126inline std::string
2127 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2128 const std::string& modeString)
2129{
2130 std::string mode;
2131
2132 if (modeString == "Static")
2133 {
2134 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2135 }
2136 else if (modeString == "MaximumPerformance")
2137 {
George Liu0fda0f12021-11-16 10:06:17 +08002138 mode =
2139 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002140 }
2141 else if (modeString == "PowerSaving")
2142 {
2143 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2144 }
2145 else
2146 {
2147 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2148 }
2149 return mode;
2150}
2151
2152/**
2153 * @brief Sets system power mode.
2154 *
2155 * @param[in] aResp Shared pointer for generating response message.
2156 * @param[in] pmode System power mode from request.
2157 *
2158 * @return None.
2159 */
2160inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2161 const std::string& pmode)
2162{
2163 BMCWEB_LOG_DEBUG << "Set power mode.";
2164
2165 std::string powerMode = validatePowerMode(aResp, pmode);
2166 if (powerMode.empty())
2167 {
2168 return;
2169 }
2170
2171 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002172 constexpr std::array<std::string_view, 1> interfaces = {
2173 "xyz.openbmc_project.Control.Power.Mode"};
2174 dbus::utility::getSubTree(
2175 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002176 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002177 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002178 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002179 if (ec)
2180 {
2181 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2182 << ec;
2183 // This is an optional D-Bus object, but user attempted to patch
2184 messages::internalError(aResp->res);
2185 return;
2186 }
2187 if (subtree.empty())
2188 {
2189 // This is an optional D-Bus object, but user attempted to patch
2190 messages::resourceNotFound(aResp->res, "ComputerSystem",
2191 "PowerMode");
2192 return;
2193 }
2194 if (subtree.size() > 1)
2195 {
2196 // More then one PowerMode object is not supported and is an
2197 // error
2198 BMCWEB_LOG_DEBUG
2199 << "Found more than 1 system D-Bus Power.Mode objects: "
2200 << subtree.size();
2201 messages::internalError(aResp->res);
2202 return;
2203 }
2204 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2205 {
2206 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2207 messages::internalError(aResp->res);
2208 return;
2209 }
2210 const std::string& path = subtree[0].first;
2211 const std::string& service = subtree[0].second.begin()->first;
2212 if (service.empty())
2213 {
2214 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2215 messages::internalError(aResp->res);
2216 return;
2217 }
2218
2219 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2220 << path;
2221
2222 // Set the Power Mode property
2223 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002224 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002225 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002226 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002227 messages::internalError(aResp->res);
2228 return;
2229 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002230 },
2231 service, path, "org.freedesktop.DBus.Properties", "Set",
2232 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2233 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002234 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002235}
2236
2237/**
Yong Li51709ff2019-09-30 14:13:04 +08002238 * @brief Translates watchdog timeout action DBUS property value to redfish.
2239 *
2240 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2241 *
2242 * @return Returns as a string, the timeout action in Redfish terms. If
2243 * translation cannot be done, returns an empty string.
2244 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002245inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002246{
2247 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2248 {
2249 return "None";
2250 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002251 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002252 {
2253 return "ResetSystem";
2254 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002255 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002256 {
2257 return "PowerDown";
2258 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002259 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002260 {
2261 return "PowerCycle";
2262 }
2263
2264 return "";
2265}
2266
2267/**
Yong Lic45f0082019-10-10 14:19:01 +08002268 *@brief Translates timeout action from Redfish to DBUS property value.
2269 *
2270 *@param[in] rfAction The timeout action in Redfish.
2271 *
2272 *@return Returns as a string, the time_out action as expected by DBUS.
2273 *If translation cannot be done, returns an empty string.
2274 */
2275
Ed Tanous23a21a12020-07-25 04:45:05 +00002276inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002277{
2278 if (rfAction == "None")
2279 {
2280 return "xyz.openbmc_project.State.Watchdog.Action.None";
2281 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002282 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002283 {
2284 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2285 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002286 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002287 {
2288 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2289 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002290 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002291 {
2292 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2293 }
2294
2295 return "";
2296}
2297
2298/**
Yong Li51709ff2019-09-30 14:13:04 +08002299 * @brief Retrieves host watchdog timer properties over DBUS
2300 *
2301 * @param[in] aResp Shared pointer for completing asynchronous calls.
2302 *
2303 * @return None.
2304 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002305inline void
2306 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002307{
2308 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002309 sdbusplus::asio::getAllProperties(
2310 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2311 "/xyz/openbmc_project/watchdog/host0",
2312 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002313 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002314 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002315 if (ec)
2316 {
2317 // watchdog service is stopped
2318 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2319 return;
2320 }
2321
2322 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2323
2324 nlohmann::json& hostWatchdogTimer =
2325 aResp->res.jsonValue["HostWatchdogTimer"];
2326
2327 // watchdog service is running/enabled
2328 hostWatchdogTimer["Status"]["State"] = "Enabled";
2329
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002330 const bool* enabled = nullptr;
2331 const std::string* expireAction = nullptr;
2332
2333 const bool success = sdbusplus::unpackPropertiesNoThrow(
2334 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2335 "ExpireAction", expireAction);
2336
2337 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002338 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002339 messages::internalError(aResp->res);
2340 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002341 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002342
2343 if (enabled != nullptr)
2344 {
2345 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2346 }
2347
2348 if (expireAction != nullptr)
2349 {
2350 std::string action = dbusToRfWatchdogAction(*expireAction);
2351 if (action.empty())
2352 {
2353 messages::internalError(aResp->res);
2354 return;
2355 }
2356 hostWatchdogTimer["TimeoutAction"] = action;
2357 }
2358 });
Yong Li51709ff2019-09-30 14:13:04 +08002359}
2360
2361/**
Yong Lic45f0082019-10-10 14:19:01 +08002362 * @brief Sets Host WatchDog Timer properties.
2363 *
2364 * @param[in] aResp Shared pointer for generating response message.
2365 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2366 * RF request.
2367 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2368 *
2369 * @return None.
2370 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002371inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002372 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002373 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002374{
2375 BMCWEB_LOG_DEBUG << "Set host watchdog";
2376
2377 if (wdtTimeOutAction)
2378 {
2379 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2380 // check if TimeOut Action is Valid
2381 if (wdtTimeOutActStr.empty())
2382 {
2383 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2384 << *wdtTimeOutAction;
2385 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2386 "TimeoutAction");
2387 return;
2388 }
2389
2390 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002391 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002392 if (ec)
2393 {
2394 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2395 messages::internalError(aResp->res);
2396 return;
2397 }
Yong Lic45f0082019-10-10 14:19:01 +08002398 },
2399 "xyz.openbmc_project.Watchdog",
2400 "/xyz/openbmc_project/watchdog/host0",
2401 "org.freedesktop.DBus.Properties", "Set",
2402 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002403 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002404 }
2405
2406 if (wdtEnable)
2407 {
2408 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002409 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002410 if (ec)
2411 {
2412 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2413 messages::internalError(aResp->res);
2414 return;
2415 }
Yong Lic45f0082019-10-10 14:19:01 +08002416 },
2417 "xyz.openbmc_project.Watchdog",
2418 "/xyz/openbmc_project/watchdog/host0",
2419 "org.freedesktop.DBus.Properties", "Set",
2420 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002421 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002422 }
2423}
2424
Chris Cain37bbf982021-09-20 10:53:09 -05002425/**
2426 * @brief Parse the Idle Power Saver properties into json
2427 *
2428 * @param[in] aResp Shared pointer for completing asynchronous calls.
2429 * @param[in] properties IPS property data from DBus.
2430 *
2431 * @return true if successful
2432 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002433inline bool
2434 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2435 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002436{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002437 const bool* enabled = nullptr;
2438 const uint8_t* enterUtilizationPercent = nullptr;
2439 const uint64_t* enterDwellTime = nullptr;
2440 const uint8_t* exitUtilizationPercent = nullptr;
2441 const uint64_t* exitDwellTime = nullptr;
2442
2443 const bool success = sdbusplus::unpackPropertiesNoThrow(
2444 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002445 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2446 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2447 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002448
2449 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002450 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002451 return false;
2452 }
2453
2454 if (enabled != nullptr)
2455 {
2456 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2457 }
2458
2459 if (enterUtilizationPercent != nullptr)
2460 {
2461 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2462 *enterUtilizationPercent;
2463 }
2464
2465 if (enterDwellTime != nullptr)
2466 {
2467 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2468 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2469 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2470 .count();
2471 }
2472
2473 if (exitUtilizationPercent != nullptr)
2474 {
2475 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2476 *exitUtilizationPercent;
2477 }
2478
2479 if (exitDwellTime != nullptr)
2480 {
2481 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2482 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2483 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2484 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002485 }
2486
2487 return true;
2488}
2489
2490/**
2491 * @brief Retrieves host watchdog timer properties over DBUS
2492 *
2493 * @param[in] aResp Shared pointer for completing asynchronous calls.
2494 *
2495 * @return None.
2496 */
2497inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2498{
2499 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2500
2501 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002502 constexpr std::array<std::string_view, 1> interfaces = {
2503 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2504 dbus::utility::getSubTree(
2505 "/", 0, interfaces,
2506 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002507 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002508 if (ec)
2509 {
2510 BMCWEB_LOG_DEBUG
2511 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2512 << ec;
2513 messages::internalError(aResp->res);
2514 return;
2515 }
2516 if (subtree.empty())
2517 {
2518 // This is an optional interface so just return
2519 // if there is no instance found
2520 BMCWEB_LOG_DEBUG << "No instances found";
2521 return;
2522 }
2523 if (subtree.size() > 1)
2524 {
2525 // More then one PowerIdlePowerSaver object is not supported and
2526 // is an error
2527 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2528 "Power.IdlePowerSaver objects: "
2529 << subtree.size();
2530 messages::internalError(aResp->res);
2531 return;
2532 }
2533 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2534 {
2535 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2536 messages::internalError(aResp->res);
2537 return;
2538 }
2539 const std::string& path = subtree[0].first;
2540 const std::string& service = subtree[0].second.begin()->first;
2541 if (service.empty())
2542 {
2543 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2544 messages::internalError(aResp->res);
2545 return;
2546 }
2547
2548 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002549 sdbusplus::asio::getAllProperties(
2550 *crow::connections::systemBus, service, path,
2551 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002552 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002553 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002554 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002555 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002556 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002557 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002558 messages::internalError(aResp->res);
2559 return;
2560 }
2561
Ed Tanous002d39b2022-05-31 08:59:27 -07002562 if (!parseIpsProperties(aResp, properties))
2563 {
2564 messages::internalError(aResp->res);
2565 return;
2566 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002567 });
George Liue99073f2022-12-09 11:06:16 +08002568 });
Chris Cain37bbf982021-09-20 10:53:09 -05002569
2570 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2571}
2572
2573/**
2574 * @brief Sets Idle Power Saver properties.
2575 *
2576 * @param[in] aResp Shared pointer for generating response message.
2577 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2578 * RF request.
2579 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2580 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2581 * before entering idle state.
2582 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2583 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2584 * before exiting idle state
2585 *
2586 * @return None.
2587 */
2588inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2589 const std::optional<bool> ipsEnable,
2590 const std::optional<uint8_t> ipsEnterUtil,
2591 const std::optional<uint64_t> ipsEnterTime,
2592 const std::optional<uint8_t> ipsExitUtil,
2593 const std::optional<uint64_t> ipsExitTime)
2594{
2595 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2596
2597 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002598 constexpr std::array<std::string_view, 1> interfaces = {
2599 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2600 dbus::utility::getSubTree(
2601 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002602 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002603 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002604 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002605 if (ec)
2606 {
2607 BMCWEB_LOG_DEBUG
2608 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2609 << ec;
2610 messages::internalError(aResp->res);
2611 return;
2612 }
2613 if (subtree.empty())
2614 {
2615 // This is an optional D-Bus object, but user attempted to patch
2616 messages::resourceNotFound(aResp->res, "ComputerSystem",
2617 "IdlePowerSaver");
2618 return;
2619 }
2620 if (subtree.size() > 1)
2621 {
2622 // More then one PowerIdlePowerSaver object is not supported and
2623 // is an error
2624 BMCWEB_LOG_DEBUG
2625 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2626 << subtree.size();
2627 messages::internalError(aResp->res);
2628 return;
2629 }
2630 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2631 {
2632 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2633 messages::internalError(aResp->res);
2634 return;
2635 }
2636 const std::string& path = subtree[0].first;
2637 const std::string& service = subtree[0].second.begin()->first;
2638 if (service.empty())
2639 {
2640 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2641 messages::internalError(aResp->res);
2642 return;
2643 }
Chris Cain37bbf982021-09-20 10:53:09 -05002644
Ed Tanous002d39b2022-05-31 08:59:27 -07002645 // Valid Power IdlePowerSaver object found, now set any values that
2646 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002647
Ed Tanous002d39b2022-05-31 08:59:27 -07002648 if (ipsEnable)
2649 {
2650 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002651 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002652 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002653 {
Ed Tanous8a592812022-06-04 09:06:59 -07002654 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002655 messages::internalError(aResp->res);
2656 return;
2657 }
2658 },
2659 service, path, "org.freedesktop.DBus.Properties", "Set",
2660 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2661 dbus::utility::DbusVariantType(*ipsEnable));
2662 }
2663 if (ipsEnterUtil)
2664 {
2665 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002666 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002667 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002668 {
Ed Tanous8a592812022-06-04 09:06:59 -07002669 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002670 messages::internalError(aResp->res);
2671 return;
2672 }
2673 },
2674 service, path, "org.freedesktop.DBus.Properties", "Set",
2675 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2676 "EnterUtilizationPercent",
2677 dbus::utility::DbusVariantType(*ipsEnterUtil));
2678 }
2679 if (ipsEnterTime)
2680 {
2681 // Convert from seconds into milliseconds for DBus
2682 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2683 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002684 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002685 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002686 {
Ed Tanous8a592812022-06-04 09:06:59 -07002687 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002688 messages::internalError(aResp->res);
2689 return;
2690 }
2691 },
2692 service, path, "org.freedesktop.DBus.Properties", "Set",
2693 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2694 "EnterDwellTime",
2695 dbus::utility::DbusVariantType(timeMilliseconds));
2696 }
2697 if (ipsExitUtil)
2698 {
2699 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002700 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002701 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002702 {
Ed Tanous8a592812022-06-04 09:06:59 -07002703 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002704 messages::internalError(aResp->res);
2705 return;
2706 }
2707 },
2708 service, path, "org.freedesktop.DBus.Properties", "Set",
2709 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2710 "ExitUtilizationPercent",
2711 dbus::utility::DbusVariantType(*ipsExitUtil));
2712 }
2713 if (ipsExitTime)
2714 {
2715 // Convert from seconds into milliseconds for DBus
2716 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2717 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002718 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002719 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002720 {
Ed Tanous8a592812022-06-04 09:06:59 -07002721 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002722 messages::internalError(aResp->res);
2723 return;
2724 }
2725 },
2726 service, path, "org.freedesktop.DBus.Properties", "Set",
2727 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2728 "ExitDwellTime",
2729 dbus::utility::DbusVariantType(timeMilliseconds));
2730 }
George Liue99073f2022-12-09 11:06:16 +08002731 });
Chris Cain37bbf982021-09-20 10:53:09 -05002732
2733 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2734}
2735
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002736inline void handleComputerSystemHead(
2737 crow::App& app, const crow::Request& req,
2738 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2739{
2740 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2741 {
2742 return;
2743 }
2744 asyncResp->res.addHeader(
2745 boost::beast::http::field::link,
2746 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2747}
2748
Yong Lic45f0082019-10-10 14:19:01 +08002749/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002750 * SystemsCollection derived class for delivering ComputerSystems Collection
2751 * Schema
2752 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002753inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002754{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002755 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002756 .privileges(redfish::privileges::headComputerSystemCollection)
2757 .methods(boost::beast::http::verb::head)(
2758 std::bind_front(handleComputerSystemHead, std::ref(app)));
2759
2760 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002761 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002762 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002763 [&app](const crow::Request& req,
2764 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002765 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002766 {
2767 return;
2768 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002769
2770 asyncResp->res.addHeader(
2771 boost::beast::http::field::link,
2772 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002773 asyncResp->res.jsonValue["@odata.type"] =
2774 "#ComputerSystemCollection.ComputerSystemCollection";
2775 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2776 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002777
Ed Tanous002d39b2022-05-31 08:59:27 -07002778 sdbusplus::asio::getProperty<std::string>(
2779 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2780 "/xyz/openbmc_project/network/hypervisor",
2781 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002782 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002783 const std::string& /*hostName*/) {
2784 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2785 ifaceArray = nlohmann::json::array();
2786 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002787
Ed Tanous002d39b2022-05-31 08:59:27 -07002788 nlohmann::json::object_t system;
2789 system["@odata.id"] = "/redfish/v1/Systems/system";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002790 ifaceArray.emplace_back(std::move(system));
Ed Tanous002d39b2022-05-31 08:59:27 -07002791 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002792 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002793 {
2794 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2795 nlohmann::json::object_t hypervisor;
2796 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002797 ifaceArray.emplace_back(std::move(hypervisor));
Ed Tanous002d39b2022-05-31 08:59:27 -07002798 count = ifaceArray.size();
2799 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002800 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002801 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002802}
Sunitha Harish462023a2020-02-19 08:34:59 -06002803
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002804/**
2805 * Function transceives data with dbus directly.
2806 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002807inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002808{
Patrick Williams89492a12023-05-10 07:51:34 -05002809 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2810 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2811 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002812 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002813 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002814
2815 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002816 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002817 if (ec)
2818 {
2819 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2820 messages::internalError(asyncResp->res);
2821 return;
2822 }
2823 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002824 },
2825 serviceName, objectPath, interfaceName, method);
2826}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002827
2828/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002829 * SystemActionsReset class supports handle POST method for Reset action.
2830 * The class retrieves and sends data directly to D-Bus.
2831 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002832inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002833{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002834 /**
2835 * Function handles POST method request.
2836 * Analyzes POST body message before sends Reset request data to D-Bus.
2837 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002838 BMCWEB_ROUTE(app,
2839 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002840 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002841 .methods(boost::beast::http::verb::post)(
2842 [&app](const crow::Request& req,
2843 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002844 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002845 {
2846 return;
2847 }
2848 std::string resetType;
2849 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2850 resetType))
2851 {
2852 return;
2853 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002854
Ed Tanous002d39b2022-05-31 08:59:27 -07002855 // Get the command and host vs. chassis
2856 std::string command;
2857 bool hostCommand = true;
2858 if ((resetType == "On") || (resetType == "ForceOn"))
2859 {
2860 command = "xyz.openbmc_project.State.Host.Transition.On";
2861 hostCommand = true;
2862 }
2863 else if (resetType == "ForceOff")
2864 {
2865 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2866 hostCommand = false;
2867 }
2868 else if (resetType == "ForceRestart")
2869 {
2870 command =
2871 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2872 hostCommand = true;
2873 }
2874 else if (resetType == "GracefulShutdown")
2875 {
2876 command = "xyz.openbmc_project.State.Host.Transition.Off";
2877 hostCommand = true;
2878 }
2879 else if (resetType == "GracefulRestart")
2880 {
2881 command =
2882 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2883 hostCommand = true;
2884 }
2885 else if (resetType == "PowerCycle")
2886 {
2887 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2888 hostCommand = true;
2889 }
2890 else if (resetType == "Nmi")
2891 {
2892 doNMI(asyncResp);
2893 return;
2894 }
2895 else
2896 {
2897 messages::actionParameterUnknown(asyncResp->res, "Reset",
2898 resetType);
2899 return;
2900 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002901
Ed Tanous002d39b2022-05-31 08:59:27 -07002902 if (hostCommand)
2903 {
2904 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002905 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002906 if (ec)
2907 {
2908 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2909 if (ec.value() == boost::asio::error::invalid_argument)
2910 {
2911 messages::actionParameterNotSupported(
2912 asyncResp->res, resetType, "Reset");
2913 }
2914 else
2915 {
2916 messages::internalError(asyncResp->res);
2917 }
2918 return;
2919 }
2920 messages::success(asyncResp->res);
2921 },
2922 "xyz.openbmc_project.State.Host",
2923 "/xyz/openbmc_project/state/host0",
2924 "org.freedesktop.DBus.Properties", "Set",
2925 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2926 dbus::utility::DbusVariantType{command});
2927 }
2928 else
2929 {
2930 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002931 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002932 if (ec)
2933 {
2934 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2935 if (ec.value() == boost::asio::error::invalid_argument)
2936 {
2937 messages::actionParameterNotSupported(
2938 asyncResp->res, resetType, "Reset");
2939 }
2940 else
2941 {
2942 messages::internalError(asyncResp->res);
2943 }
2944 return;
2945 }
2946 messages::success(asyncResp->res);
2947 },
2948 "xyz.openbmc_project.State.Chassis",
2949 "/xyz/openbmc_project/state/chassis0",
2950 "org.freedesktop.DBus.Properties", "Set",
2951 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2952 dbus::utility::DbusVariantType{command});
2953 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002954 });
2955}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002956
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002957inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002958 App& app, const crow::Request& req,
2959 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2960{
2961 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2962 {
2963 return;
2964 }
2965
2966 asyncResp->res.addHeader(
2967 boost::beast::http::field::link,
2968 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2969}
2970
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002971inline void afterPortRequest(
2972 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2973 const boost::system::error_code& ec,
2974 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2975{
2976 if (ec)
2977 {
2978 messages::internalError(asyncResp->res);
2979 return;
2980 }
2981 for (const auto& data : socketData)
2982 {
2983 const std::string& socketPath = get<0>(data);
2984 const std::string& protocolName = get<1>(data);
2985 bool isProtocolEnabled = get<2>(data);
2986 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2987 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2988 // need to retrieve port number for
2989 // obmc-console-ssh service
2990 if (protocolName == "SSH")
2991 {
2992 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002993 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002994 int portNumber) {
2995 if (ec1)
2996 {
2997 messages::internalError(asyncResp->res);
2998 return;
2999 }
3000 nlohmann::json& dataJson1 =
3001 asyncResp->res.jsonValue["SerialConsole"];
3002 dataJson1[protocolName]["Port"] = portNumber;
3003 });
3004 }
3005 }
3006}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003007/**
Ed Tanous66173382018-08-15 18:20:59 -07003008 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003009 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003010inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003011{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003012 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
3013 .privileges(redfish::privileges::headComputerSystem)
3014 .methods(boost::beast::http::verb::head)(
3015 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07003016 /**
3017 * Functions triggers appropriate requests on DBus
3018 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003019 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003020 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003021 .methods(boost::beast::http::verb::get)(
3022 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003023 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3024 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003025 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003026 {
3027 return;
3028 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003029
3030 if (systemName == "hypervisor")
3031 {
3032 handleHypervisorSystemGet(asyncResp);
3033 return;
3034 }
3035
Ed Tanous22d268c2022-05-19 09:39:07 -07003036 if (systemName != "system")
3037 {
3038 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3039 systemName);
3040 return;
3041 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003042 asyncResp->res.addHeader(
3043 boost::beast::http::field::link,
3044 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003045 asyncResp->res.jsonValue["@odata.type"] =
3046 "#ComputerSystem.v1_16_0.ComputerSystem";
3047 asyncResp->res.jsonValue["Name"] = "system";
3048 asyncResp->res.jsonValue["Id"] = "system";
3049 asyncResp->res.jsonValue["SystemType"] = "Physical";
3050 asyncResp->res.jsonValue["Description"] = "Computer System";
3051 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3052 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3053 "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -07003054 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3055 "Disabled";
Ninad Palsulecf0e0042023-05-18 17:18:09 -05003056 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3057 uint64_t(0);
Ed Tanous002d39b2022-05-31 08:59:27 -07003058 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003059
Ed Tanous002d39b2022-05-31 08:59:27 -07003060 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3061 "/redfish/v1/Systems/system/Processors";
3062 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3063 "/redfish/v1/Systems/system/Memory";
3064 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3065 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003066 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3067 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003068
Ed Tanous002d39b2022-05-31 08:59:27 -07003069 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3070 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3071 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3072 ["@Redfish.ActionInfo"] =
3073 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003074
Ed Tanous002d39b2022-05-31 08:59:27 -07003075 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3076 "/redfish/v1/Systems/system/LogServices";
3077 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3078 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003079
Ed Tanous002d39b2022-05-31 08:59:27 -07003080 nlohmann::json::array_t managedBy;
3081 nlohmann::json& manager = managedBy.emplace_back();
3082 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3083 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3084 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3085 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003086
Ed Tanous002d39b2022-05-31 08:59:27 -07003087 // Fill in SerialConsole info
3088 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3089 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3090 true;
Ed Tanous14766872022-03-15 10:44:42 -07003091
Ed Tanous002d39b2022-05-31 08:59:27 -07003092 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3093 true;
3094 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3095 asyncResp->res
3096 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3097 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003098 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3099 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003100
3101#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003102 // Fill in GraphicalConsole info
3103 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3104 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3105 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003106 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3107 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003108
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003109#endif // BMCWEB_ENABLE_KVM
George Liu7a1dbc42022-12-07 16:03:22 +08003110 constexpr std::array<std::string_view, 4> inventoryForSystems{
Ed Tanous002d39b2022-05-31 08:59:27 -07003111 "xyz.openbmc_project.Inventory.Item.Dimm",
3112 "xyz.openbmc_project.Inventory.Item.Cpu",
3113 "xyz.openbmc_project.Inventory.Item.Drive",
3114 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003115
Ed Tanous002d39b2022-05-31 08:59:27 -07003116 auto health = std::make_shared<HealthPopulate>(asyncResp);
George Liu7a1dbc42022-12-07 16:03:22 +08003117 dbus::utility::getSubTreePaths(
3118 "/", 0, inventoryForSystems,
3119 [health](const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07003120 const std::vector<std::string>& resp) {
3121 if (ec)
3122 {
3123 // no inventory
3124 return;
3125 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003126
Ed Tanous002d39b2022-05-31 08:59:27 -07003127 health->inventory = resp;
George Liu7a1dbc42022-12-07 16:03:22 +08003128 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003129
Ed Tanous002d39b2022-05-31 08:59:27 -07003130 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003131
Ed Tanous002d39b2022-05-31 08:59:27 -07003132 getMainChassisId(asyncResp,
3133 [](const std::string& chassisId,
3134 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3135 nlohmann::json::array_t chassisArray;
3136 nlohmann::json& chassis = chassisArray.emplace_back();
Ed Tanousef4c65b2023-04-24 15:28:50 -07003137 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3138 chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003139 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3140 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003141
Ed Tanous002d39b2022-05-31 08:59:27 -07003142 getLocationIndicatorActive(asyncResp);
3143 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3144 getIndicatorLedState(asyncResp);
3145 getComputerSystem(asyncResp, health);
3146 getHostState(asyncResp);
3147 getBootProperties(asyncResp);
3148 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003149 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003150 getPCIeDeviceList(asyncResp, "PCIeDevices");
3151 getHostWatchdogTimer(asyncResp);
3152 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003153 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003154 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003155#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003156 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003157#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003158 getTrustedModuleRequiredToBoot(asyncResp);
3159 getPowerMode(asyncResp);
3160 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003161 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003162
Ed Tanous22d268c2022-05-19 09:39:07 -07003163 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003164 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003165 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003166 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003167 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3168 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003169 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003170 {
3171 return;
3172 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003173 if (systemName != "system")
3174 {
3175 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3176 systemName);
3177 return;
3178 }
3179
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003180 asyncResp->res.addHeader(
3181 boost::beast::http::field::link,
3182 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3183
Ed Tanous002d39b2022-05-31 08:59:27 -07003184 std::optional<bool> locationIndicatorActive;
3185 std::optional<std::string> indicatorLed;
3186 std::optional<std::string> assetTag;
3187 std::optional<std::string> powerRestorePolicy;
3188 std::optional<std::string> powerMode;
3189 std::optional<bool> wdtEnable;
3190 std::optional<std::string> wdtTimeOutAction;
3191 std::optional<std::string> bootSource;
3192 std::optional<std::string> bootType;
3193 std::optional<std::string> bootEnable;
3194 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003195 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003196 std::optional<bool> bootTrustedModuleRequired;
3197 std::optional<bool> ipsEnable;
3198 std::optional<uint8_t> ipsEnterUtil;
3199 std::optional<uint64_t> ipsEnterTime;
3200 std::optional<uint8_t> ipsExitUtil;
3201 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003202
Ed Tanous002d39b2022-05-31 08:59:27 -07003203 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003204 if (!json_util::readJsonPatch(
3205 req, asyncResp->res,
3206 "IndicatorLED", indicatorLed,
3207 "LocationIndicatorActive", locationIndicatorActive,
3208 "AssetTag", assetTag,
3209 "PowerRestorePolicy", powerRestorePolicy,
3210 "PowerMode", powerMode,
3211 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3212 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3213 "Boot/BootSourceOverrideTarget", bootSource,
3214 "Boot/BootSourceOverrideMode", bootType,
3215 "Boot/BootSourceOverrideEnabled", bootEnable,
3216 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003217 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003218 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3219 "IdlePowerSaver/Enabled", ipsEnable,
3220 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3221 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3222 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3223 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3224 {
3225 return;
3226 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003227 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003228
Ed Tanous002d39b2022-05-31 08:59:27 -07003229 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003230
Ed Tanous002d39b2022-05-31 08:59:27 -07003231 if (assetTag)
3232 {
3233 setAssetTag(asyncResp, *assetTag);
3234 }
James Feistb49ac872019-05-21 15:12:01 -07003235
Ed Tanous002d39b2022-05-31 08:59:27 -07003236 if (wdtEnable || wdtTimeOutAction)
3237 {
3238 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3239 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003240
Ed Tanous002d39b2022-05-31 08:59:27 -07003241 if (bootSource || bootType || bootEnable)
3242 {
3243 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3244 }
3245 if (bootAutomaticRetry)
3246 {
3247 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3248 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003249
Corey Hardesty797d5da2022-04-26 17:54:52 +08003250 if (bootAutomaticRetryAttempts)
3251 {
3252 setAutomaticRetryAttempts(asyncResp,
3253 bootAutomaticRetryAttempts.value());
3254 }
3255
Ed Tanous002d39b2022-05-31 08:59:27 -07003256 if (bootTrustedModuleRequired)
3257 {
3258 setTrustedModuleRequiredToBoot(asyncResp,
3259 *bootTrustedModuleRequired);
3260 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003261
Ed Tanous002d39b2022-05-31 08:59:27 -07003262 if (locationIndicatorActive)
3263 {
3264 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3265 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003266
Ed Tanous002d39b2022-05-31 08:59:27 -07003267 // TODO (Gunnar): Remove IndicatorLED after enough time has
3268 // passed
3269 if (indicatorLed)
3270 {
3271 setIndicatorLedState(asyncResp, *indicatorLed);
3272 asyncResp->res.addHeader(boost::beast::http::field::warning,
3273 "299 - \"IndicatorLED is deprecated. Use "
3274 "LocationIndicatorActive instead.\"");
3275 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003276
Ed Tanous002d39b2022-05-31 08:59:27 -07003277 if (powerRestorePolicy)
3278 {
3279 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3280 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003281
Ed Tanous002d39b2022-05-31 08:59:27 -07003282 if (powerMode)
3283 {
3284 setPowerMode(asyncResp, *powerMode);
3285 }
Chris Cain37bbf982021-09-20 10:53:09 -05003286
Ed Tanous002d39b2022-05-31 08:59:27 -07003287 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3288 ipsExitTime)
3289 {
3290 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3291 ipsExitUtil, ipsExitTime);
3292 }
3293 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003294}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303295
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003296inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003297 crow::App& app, const crow::Request& req,
3298 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3299{
3300 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3301 {
3302 return;
3303 }
3304 asyncResp->res.addHeader(
3305 boost::beast::http::field::link,
3306 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3307}
3308
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303309/**
3310 * SystemResetActionInfo derived class for delivering Computer Systems
3311 * ResetType AllowableValues using ResetInfo schema.
3312 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003313inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303314{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003315 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3316 .privileges(redfish::privileges::headActionInfo)
3317 .methods(boost::beast::http::verb::head)(std::bind_front(
3318 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303319 /**
3320 * Functions triggers appropriate requests on DBus
3321 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003322 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003323 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003324 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003325 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003326 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3327 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003328 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003329 {
3330 return;
3331 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003332
3333 if (systemName == "hypervisor")
3334 {
3335 handleHypervisorResetActionGet(asyncResp);
3336 return;
3337 }
3338
Ed Tanous22d268c2022-05-19 09:39:07 -07003339 if (systemName != "system")
3340 {
3341 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3342 systemName);
3343 return;
3344 }
3345
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003346 asyncResp->res.addHeader(
3347 boost::beast::http::field::link,
3348 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003349
Ed Tanous002d39b2022-05-31 08:59:27 -07003350 asyncResp->res.jsonValue["@odata.id"] =
3351 "/redfish/v1/Systems/system/ResetActionInfo";
3352 asyncResp->res.jsonValue["@odata.type"] =
3353 "#ActionInfo.v1_1_2.ActionInfo";
3354 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3355 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003356
3357 nlohmann::json::array_t parameters;
3358 nlohmann::json::object_t parameter;
3359
3360 parameter["Name"] = "ResetType";
3361 parameter["Required"] = true;
3362 parameter["DataType"] = "String";
3363 nlohmann::json::array_t allowableValues;
3364 allowableValues.emplace_back("On");
3365 allowableValues.emplace_back("ForceOff");
3366 allowableValues.emplace_back("ForceOn");
3367 allowableValues.emplace_back("ForceRestart");
3368 allowableValues.emplace_back("GracefulRestart");
3369 allowableValues.emplace_back("GracefulShutdown");
3370 allowableValues.emplace_back("PowerCycle");
3371 allowableValues.emplace_back("Nmi");
3372 parameter["AllowableValues"] = std::move(allowableValues);
3373 parameters.emplace_back(std::move(parameter));
3374
3375 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003376 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003377}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003378} // namespace redfish