blob: 573bf881dbe5bd8b5783967a7e3f90fe6bdfc063 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070021#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070023#include "health.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060024#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080025#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080026#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070027#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080028#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "registries/privilege_registry.hpp"
30#include "utils/dbus_utils.hpp"
31#include "utils/json_utils.hpp"
32#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070033#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080034
Ed Tanous9712f8a2018-09-21 13:38:49 -070035#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080036#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070037#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070038#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020039#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050040
George Liu7a1dbc42022-12-07 16:03:22 +080041#include <array>
42#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080043#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020044
Ed Tanous1abe55e2018-09-05 08:30:59 -070045namespace redfish
46{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020047
Abhishek Patel5c3e9272021-06-24 10:11:33 -050048const static std::array<std::pair<std::string_view, std::string_view>, 2>
49 protocolToDBusForSystems{
50 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
51
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052/**
53 * @brief Updates the Functional State of DIMMs
54 *
55 * @param[in] aResp Shared pointer for completing asynchronous calls
56 * @param[in] dimmState Dimm's Functional state, true/false
57 *
58 * @return None.
59 */
zhanghch058d1b46d2021-04-01 11:18:24 +080060inline void
61 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070062 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050063{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070064 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065
Gunnar Mills4e0453b2020-07-08 14:00:30 -050066 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050067 // Update STATE only if previous State was DISABLED and current Dimm is
68 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070069 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050070 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
71 if (prevMemSummary == "Disabled")
72 {
Ed Tanouse05aec52022-01-25 10:28:56 -080073 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050074 {
75 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
76 "Enabled";
77 }
78 }
79}
80
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050082 * @brief Update "ProcessorSummary" "Status" "State" based on
83 * CPU Functional State
84 *
85 * @param[in] aResp Shared pointer for completing asynchronous calls
86 * @param[in] cpuFunctionalState is CPU functional true/false
87 *
88 * @return None.
89 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070090inline void
91 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
92 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070094 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050095
Ed Tanous02cad962022-06-30 16:50:15 -070096 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050097 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
98
Gunnar Mills4e0453b2020-07-08 14:00:30 -050099 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500100 // Update STATE only if previous State was Non_Functional and current CPU is
101 // Functional.
102 if (prevProcState == "Disabled")
103 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800104 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500105 {
106 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
107 "Enabled";
108 }
109 }
110}
111
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500112/*
113 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
114 *
115 * @param[in] aResp Shared pointer for completing asynchronous calls
116 * @param[in] cpuPresenceState CPU present or not
117 *
118 * @return None.
119 */
120inline void
121 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
122 bool isCpuPresent)
123{
124 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
125
126 if (isCpuPresent)
127 {
128 nlohmann::json& procCount =
129 aResp->res.jsonValue["ProcessorSummary"]["Count"];
130 auto* procCountPtr =
131 procCount.get_ptr<nlohmann::json::number_integer_t*>();
132 if (procCountPtr != nullptr)
133 {
134 // shouldn't be possible to be nullptr
135 *procCountPtr += 1;
136 }
137 }
138}
139
Ali Ahmed382d6472021-09-03 16:53:53 -0500140inline void getProcessorProperties(
141 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
142 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
143 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500144{
Ali Ahmed03fbed92021-09-03 02:33:43 -0500145 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
146
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200147 // TODO: Get Model
148
149 const uint16_t* coreCount = nullptr;
150
151 const bool success = sdbusplus::unpackPropertiesNoThrow(
152 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
153
154 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500155 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200156 messages::internalError(aResp->res);
157 return;
158 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200160 if (coreCount != nullptr)
161 {
162 nlohmann::json& coreCountJson =
163 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
164 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200166 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500167 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200168 coreCountJson = *coreCount;
169 }
170 else
171 {
172 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500173 }
174 }
175}
176
177/*
178 * @brief Get ProcessorSummary fields
179 *
180 * @param[in] aResp Shared pointer for completing asynchronous calls
181 * @param[in] service dbus service for Cpu Information
182 * @param[in] path dbus path for Cpu
183 *
184 * @return None.
185 */
186inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
187 const std::string& service,
188 const std::string& path)
189{
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800190 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500191 const bool cpuPresenceCheck) {
192 if (ec3)
193 {
194 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
195 return;
196 }
197 modifyCpuPresenceState(aResp, cpuPresenceCheck);
198 };
199
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500200 // Get the Presence of CPU
201 sdbusplus::asio::getProperty<bool>(
202 *crow::connections::systemBus, service, path,
203 "xyz.openbmc_project.Inventory.Item", "Present",
204 std::move(getCpuPresenceState));
205
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500206 if constexpr (bmcwebEnableProcMemStatus)
207 {
208 auto getCpuFunctionalState =
209 [aResp](const boost::system::error_code& ec3,
210 const bool cpuFunctionalCheck) {
211 if (ec3)
212 {
213 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
214 return;
215 }
216 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
217 };
Ali Ahmed382d6472021-09-03 16:53:53 -0500218
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500219 // Get the Functional State
220 sdbusplus::asio::getProperty<bool>(
221 *crow::connections::systemBus, service, path,
222 "xyz.openbmc_project.State.Decorator.OperationalStatus",
223 "Functional", std::move(getCpuFunctionalState));
224 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500225
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200226 sdbusplus::asio::getAllProperties(
227 *crow::connections::systemBus, service, path,
228 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500229 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800230 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800231 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700232 if (ec2)
233 {
234 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
235 messages::internalError(aResp->res);
236 return;
237 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500238 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200239 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500240}
241
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500242/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500243 * @brief processMemoryProperties fields
244 *
245 * @param[in] aResp Shared pointer for completing asynchronous calls
246 * @param[in] service dbus service for memory Information
247 * @param[in] path dbus path for Memory
248 * @param[in] DBUS properties for memory
249 *
250 * @return None.
251 */
252inline void
253 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500254 [[maybe_unused]] const std::string& service,
255 [[maybe_unused]] const std::string& path,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500256 const dbus::utility::DBusPropertiesMap& properties)
257{
258 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Dimm properties.";
259
260 if (properties.empty())
261 {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500262 if constexpr (bmcwebEnableProcMemStatus)
263 {
264 sdbusplus::asio::getProperty<bool>(
265 *crow::connections::systemBus, service, path,
266 "xyz.openbmc_project.State."
267 "Decorator.OperationalStatus",
268 "Functional",
269 [aResp](const boost::system::error_code& ec3, bool dimmState) {
270 if (ec3)
271 {
272 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
273 return;
274 }
275 updateDimmProperties(aResp, dimmState);
276 });
277 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500278 return;
279 }
280
281 const size_t* memorySizeInKB = nullptr;
282
283 const bool success = sdbusplus::unpackPropertiesNoThrow(
284 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
285 memorySizeInKB);
286
287 if (!success)
288 {
289 messages::internalError(aResp->res);
290 return;
291 }
292
293 if (memorySizeInKB != nullptr)
294 {
295 nlohmann::json& totalMemory =
296 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
297 const uint64_t* preValue = totalMemory.get_ptr<const uint64_t*>();
298 if (preValue == nullptr)
299 {
300 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
301 *memorySizeInKB / static_cast<size_t>(1024 * 1024);
302 }
303 else
304 {
305 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
306 *memorySizeInKB / static_cast<size_t>(1024 * 1024) + *preValue;
307 }
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500308 if constexpr (bmcwebEnableProcMemStatus)
309 {
310 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
311 "Enabled";
312 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500313 }
314}
315
316/*
317 * @brief Get getMemorySummary fields
318 *
319 * @param[in] aResp Shared pointer for completing asynchronous calls
320 * @param[in] service dbus service for memory Information
321 * @param[in] path dbus path for memory
322 *
323 * @return None.
324 */
325inline void getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
326 const std::string& service,
327 const std::string& path)
328{
329 sdbusplus::asio::getAllProperties(
330 *crow::connections::systemBus, service, path,
331 "xyz.openbmc_project.Inventory.Item.Dimm",
332 [aResp, service,
333 path](const boost::system::error_code& ec2,
334 const dbus::utility::DBusPropertiesMap& properties) {
335 if (ec2)
336 {
337 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
338 messages::internalError(aResp->res);
339 return;
340 }
341 processMemoryProperties(aResp, service, path, properties);
342 });
343}
344
345/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700346 * @brief Retrieves computer system properties over dbus
347 *
348 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500349 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700350 *
351 * @return None.
352 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700353inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800354 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700355 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700356{
Ed Tanous6c34de42018-08-29 13:37:36 -0700357 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800358 constexpr std::array<std::string_view, 5> interfaces = {
359 "xyz.openbmc_project.Inventory.Decorator.Asset",
360 "xyz.openbmc_project.Inventory.Item.Cpu",
361 "xyz.openbmc_project.Inventory.Item.Dimm",
362 "xyz.openbmc_project.Inventory.Item.System",
363 "xyz.openbmc_project.Common.UUID",
364 };
365 dbus::utility::getSubTree(
366 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800367 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800368 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800369 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700370 if (ec)
371 {
372 BMCWEB_LOG_DEBUG << "DBUS response error";
373 messages::internalError(aResp->res);
374 return;
375 }
376 // Iterate over all retrieved ObjectPaths.
377 for (const std::pair<
378 std::string,
379 std::vector<std::pair<std::string, std::vector<std::string>>>>&
380 object : subtree)
381 {
382 const std::string& path = object.first;
383 BMCWEB_LOG_DEBUG << "Got path: " << path;
384 const std::vector<std::pair<std::string, std::vector<std::string>>>&
385 connectionNames = object.second;
386 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700387 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700388 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700389 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700390
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500391 std::shared_ptr<HealthPopulate> memoryHealth = nullptr;
392 std::shared_ptr<HealthPopulate> cpuHealth = nullptr;
Ed Tanous002d39b2022-05-31 08:59:27 -0700393
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500394 if constexpr (bmcwebEnableProcMemStatus)
Willy Tu13451e32023-05-24 16:08:18 -0700395 {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500396 memoryHealth = std::make_shared<HealthPopulate>(
397 aResp, "/MemorySummary/Status"_json_pointer);
Willy Tu13451e32023-05-24 16:08:18 -0700398 systemHealth->children.emplace_back(memoryHealth);
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500399
400 if constexpr (bmcwebEnableHealthPopulate)
401 {
402 cpuHealth = std::make_shared<HealthPopulate>(
403 aResp, "/ProcessorSummary/Status"_json_pointer);
404
405 systemHealth->children.emplace_back(cpuHealth);
406 }
Willy Tu13451e32023-05-24 16:08:18 -0700407 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700408
409 // This is not system, so check if it's cpu, dimm, UUID or
410 // BiosVer
411 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700412 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700413 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700414 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700415 if (interfaceName ==
416 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700417 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700418 BMCWEB_LOG_DEBUG
419 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500420
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500421 getMemorySummary(aResp, connection.first, path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700422
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500423 if constexpr (bmcwebEnableProcMemStatus)
424 {
425 memoryHealth->inventory.emplace_back(path);
426 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700427 }
428 else if (interfaceName ==
429 "xyz.openbmc_project.Inventory.Item.Cpu")
430 {
431 BMCWEB_LOG_DEBUG
432 << "Found Cpu, now get its properties.";
433
434 getProcessorSummary(aResp, connection.first, path);
435
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500436 if constexpr (bmcwebEnableProcMemStatus)
437 {
438 cpuHealth->inventory.emplace_back(path);
439 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700440 }
441 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
442 {
443 BMCWEB_LOG_DEBUG
444 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200445
446 sdbusplus::asio::getAllProperties(
447 *crow::connections::systemBus, connection.first,
448 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800449 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700450 const dbus::utility::DBusPropertiesMap&
451 properties) {
452 if (ec3)
453 {
454 BMCWEB_LOG_DEBUG << "DBUS response error "
455 << ec3;
456 messages::internalError(aResp->res);
457 return;
458 }
459 BMCWEB_LOG_DEBUG << "Got " << properties.size()
460 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700461
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200462 const std::string* uUID = nullptr;
463
464 const bool success =
465 sdbusplus::unpackPropertiesNoThrow(
466 dbus_utils::UnpackErrorPrinter(),
467 properties, "UUID", uUID);
468
469 if (!success)
470 {
471 messages::internalError(aResp->res);
472 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700473 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200474
475 if (uUID != nullptr)
476 {
477 std::string valueStr = *uUID;
478 if (valueStr.size() == 32)
479 {
480 valueStr.insert(8, 1, '-');
481 valueStr.insert(13, 1, '-');
482 valueStr.insert(18, 1, '-');
483 valueStr.insert(23, 1, '-');
484 }
485 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
486 aResp->res.jsonValue["UUID"] = valueStr;
487 }
488 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700489 }
490 else if (interfaceName ==
491 "xyz.openbmc_project.Inventory.Item.System")
492 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200493 sdbusplus::asio::getAllProperties(
494 *crow::connections::systemBus, connection.first,
495 path,
496 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800497 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700498 const dbus::utility::DBusPropertiesMap&
499 propertiesList) {
500 if (ec2)
501 {
502 // doesn't have to include this
503 // interface
504 return;
505 }
506 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
507 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200508
509 const std::string* partNumber = nullptr;
510 const std::string* serialNumber = nullptr;
511 const std::string* manufacturer = nullptr;
512 const std::string* model = nullptr;
513 const std::string* subModel = nullptr;
514
515 const bool success =
516 sdbusplus::unpackPropertiesNoThrow(
517 dbus_utils::UnpackErrorPrinter(),
518 propertiesList, "PartNumber", partNumber,
519 "SerialNumber", serialNumber,
520 "Manufacturer", manufacturer, "Model",
521 model, "SubModel", subModel);
522
523 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700524 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200525 messages::internalError(aResp->res);
526 return;
527 }
528
529 if (partNumber != nullptr)
530 {
531 aResp->res.jsonValue["PartNumber"] =
532 *partNumber;
533 }
534
535 if (serialNumber != nullptr)
536 {
537 aResp->res.jsonValue["SerialNumber"] =
538 *serialNumber;
539 }
540
541 if (manufacturer != nullptr)
542 {
543 aResp->res.jsonValue["Manufacturer"] =
544 *manufacturer;
545 }
546
547 if (model != nullptr)
548 {
549 aResp->res.jsonValue["Model"] = *model;
550 }
551
552 if (subModel != nullptr)
553 {
554 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700555 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500556
Ed Tanous002d39b2022-05-31 08:59:27 -0700557 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700558 sw_util::populateSoftwareInformation(
559 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700560 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200561 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700562
Ed Tanous002d39b2022-05-31 08:59:27 -0700563 sdbusplus::asio::getProperty<std::string>(
564 *crow::connections::systemBus, connection.first,
565 path,
566 "xyz.openbmc_project.Inventory.Decorator."
567 "AssetTag",
568 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800569 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700570 const std::string& value) {
571 if (ec2)
572 {
573 // doesn't have to include this
574 // interface
575 return;
576 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700577
Ed Tanous002d39b2022-05-31 08:59:27 -0700578 aResp->res.jsonValue["AssetTag"] = value;
579 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700580 }
581 }
582 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700583 }
Ed Tanous66173382018-08-15 18:20:59 -0700584 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700585}
586
587/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700588 * @brief Retrieves host state properties over dbus
589 *
590 * @param[in] aResp Shared pointer for completing asynchronous calls.
591 *
592 * @return None.
593 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800594inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700595{
596 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700597 sdbusplus::asio::getProperty<std::string>(
598 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
599 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
600 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800601 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700602 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700603 if (ec)
604 {
605 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700606 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700607 // Service not available, no error, just don't return
608 // host state info
609 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700610 return;
611 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700612 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
613 messages::internalError(aResp->res);
614 return;
615 }
Ed Tanous66173382018-08-15 18:20:59 -0700616
Ed Tanous002d39b2022-05-31 08:59:27 -0700617 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
618 // Verify Host State
619 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
620 {
621 aResp->res.jsonValue["PowerState"] = "On";
622 aResp->res.jsonValue["Status"]["State"] = "Enabled";
623 }
624 else if (hostState ==
625 "xyz.openbmc_project.State.Host.HostState.Quiesced")
626 {
627 aResp->res.jsonValue["PowerState"] = "On";
628 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
629 }
630 else if (hostState ==
631 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
632 {
633 aResp->res.jsonValue["PowerState"] = "On";
634 aResp->res.jsonValue["Status"]["State"] = "InTest";
635 }
636 else if (
637 hostState ==
638 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
639 {
640 aResp->res.jsonValue["PowerState"] = "PoweringOn";
641 aResp->res.jsonValue["Status"]["State"] = "Starting";
642 }
643 else if (hostState ==
644 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
645 {
646 aResp->res.jsonValue["PowerState"] = "PoweringOff";
647 aResp->res.jsonValue["Status"]["State"] = "Disabled";
648 }
649 else
650 {
651 aResp->res.jsonValue["PowerState"] = "Off";
652 aResp->res.jsonValue["Status"]["State"] = "Disabled";
653 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700654 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700655}
656
657/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500658 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530659 *
660 * @param[in] dbusSource The boot source in DBUS speak.
661 *
662 * @return Returns as a string, the boot source in Redfish terms. If translation
663 * cannot be done, returns an empty string.
664 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000665inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530666{
667 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
668 {
669 return "None";
670 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700671 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530672 {
673 return "Hdd";
674 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700675 if (dbusSource ==
676 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530677 {
678 return "Cd";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "Pxe";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 if (dbusSource ==
685 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700686 {
687 return "Usb";
688 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700689 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530690}
691
692/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300693 * @brief Translates boot type DBUS property value to redfish.
694 *
695 * @param[in] dbusType The boot type in DBUS speak.
696 *
697 * @return Returns as a string, the boot type in Redfish terms. If translation
698 * cannot be done, returns an empty string.
699 */
700inline std::string dbusToRfBootType(const std::string& dbusType)
701{
702 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
703 {
704 return "Legacy";
705 }
706 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
707 {
708 return "UEFI";
709 }
710 return "";
711}
712
713/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500714 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530715 *
716 * @param[in] dbusMode The boot mode in DBUS speak.
717 *
718 * @return Returns as a string, the boot mode in Redfish terms. If translation
719 * cannot be done, returns an empty string.
720 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000721inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530722{
723 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
724 {
725 return "None";
726 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700727 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530728 {
729 return "Diags";
730 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700731 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530732 {
733 return "BiosSetup";
734 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700735 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530736}
737
738/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600739 * @brief Translates boot progress DBUS property value to redfish.
740 *
741 * @param[in] dbusBootProgress The boot progress in DBUS speak.
742 *
743 * @return Returns as a string, the boot progress in Redfish terms. If
744 * translation cannot be done, returns "None".
745 */
746inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
747{
748 // Now convert the D-Bus BootProgress to the appropriate Redfish
749 // enum
750 std::string rfBpLastState = "None";
751 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
752 "ProgressStages.Unspecified")
753 {
754 rfBpLastState = "None";
755 }
756 else if (dbusBootProgress ==
757 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
758 "PrimaryProcInit")
759 {
760 rfBpLastState = "PrimaryProcessorInitializationStarted";
761 }
762 else if (dbusBootProgress ==
763 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
764 "BusInit")
765 {
766 rfBpLastState = "BusInitializationStarted";
767 }
768 else if (dbusBootProgress ==
769 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
770 "MemoryInit")
771 {
772 rfBpLastState = "MemoryInitializationStarted";
773 }
774 else if (dbusBootProgress ==
775 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
776 "SecondaryProcInit")
777 {
778 rfBpLastState = "SecondaryProcessorInitializationStarted";
779 }
780 else if (dbusBootProgress ==
781 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
782 "PCIInit")
783 {
784 rfBpLastState = "PCIResourceConfigStarted";
785 }
786 else if (dbusBootProgress ==
787 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
788 "SystemSetup")
789 {
790 rfBpLastState = "SetupEntered";
791 }
792 else if (dbusBootProgress ==
793 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
794 "SystemInitComplete")
795 {
796 rfBpLastState = "SystemHardwareInitializationComplete";
797 }
798 else if (dbusBootProgress ==
799 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
800 "OSStart")
801 {
802 rfBpLastState = "OSBootStarted";
803 }
804 else if (dbusBootProgress ==
805 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
806 "OSRunning")
807 {
808 rfBpLastState = "OSRunning";
809 }
810 else
811 {
812 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
813 << dbusBootProgress;
814 // Just return the default
815 }
816 return rfBpLastState;
817}
818
819/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500820 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530821 *
822 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 * @param[out] bootSource The DBus source
824 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530825 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700826 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530827 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800828inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500829 const std::string& rfSource,
830 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530831{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300832 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
833 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700834
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530835 if (rfSource == "None")
836 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700837 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530838 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700839 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530840 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700841 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
842 }
843 else if (rfSource == "Hdd")
844 {
845 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
846 }
847 else if (rfSource == "Diags")
848 {
849 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
850 }
851 else if (rfSource == "Cd")
852 {
853 bootSource =
854 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
855 }
856 else if (rfSource == "BiosSetup")
857 {
858 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530859 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700860 else if (rfSource == "Usb")
861 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700862 bootSource =
863 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700864 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530865 else
866 {
George Liu0fda0f12021-11-16 10:06:17 +0800867 BMCWEB_LOG_DEBUG
868 << "Invalid property value for BootSourceOverrideTarget: "
869 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700870 messages::propertyValueNotInList(aResp->res, rfSource,
871 "BootSourceTargetOverride");
872 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530873 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700874 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530875}
Ali Ahmed19817712021-06-29 17:01:52 -0500876
Andrew Geissler978b8802020-11-19 13:36:40 -0600877/**
878 * @brief Retrieves boot progress of the system
879 *
880 * @param[in] aResp Shared pointer for generating response message.
881 *
882 * @return None.
883 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800884inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600885{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700886 sdbusplus::asio::getProperty<std::string>(
887 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
888 "/xyz/openbmc_project/state/host0",
889 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800890 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700891 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700892 if (ec)
893 {
894 // BootProgress is an optional object so just do nothing if
895 // not found
896 return;
897 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600898
Ed Tanous002d39b2022-05-31 08:59:27 -0700899 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600900
Ed Tanous002d39b2022-05-31 08:59:27 -0700901 aResp->res.jsonValue["BootProgress"]["LastState"] =
902 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700903 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600904}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530905
906/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000907 * @brief Retrieves boot progress Last Update of the system
908 *
909 * @param[in] aResp Shared pointer for generating response message.
910 *
911 * @return None.
912 */
913inline void getBootProgressLastStateTime(
914 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
915{
916 sdbusplus::asio::getProperty<uint64_t>(
917 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
918 "/xyz/openbmc_project/state/host0",
919 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800920 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000921 const uint64_t lastStateTime) {
922 if (ec)
923 {
924 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
925 return;
926 }
927
928 // BootProgressLastUpdate is the last time the BootProgress property
929 // was updated. The time is the Epoch time, number of microseconds
930 // since 1 Jan 1970 00::00::00 UTC."
931 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
932 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
933
934 // Convert to ISO 8601 standard
935 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
936 redfish::time_utils::getDateTimeUintUs(lastStateTime);
937 });
938}
939
940/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300941 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300942 *
943 * @param[in] aResp Shared pointer for generating response message.
944 *
945 * @return None.
946 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300947
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300948inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300949{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700950 sdbusplus::asio::getProperty<std::string>(
951 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
952 "/xyz/openbmc_project/control/host0/boot",
953 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800954 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700955 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700956 if (ec)
957 {
958 // not an error, don't have to have the interface
959 return;
960 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300961
Ed Tanous002d39b2022-05-31 08:59:27 -0700962 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300963
Ed Tanous002d39b2022-05-31 08:59:27 -0700964 aResp->res.jsonValue["Boot"]
965 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700966 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300967
Ed Tanous002d39b2022-05-31 08:59:27 -0700968 auto rfType = dbusToRfBootType(bootType);
969 if (rfType.empty())
970 {
971 messages::internalError(aResp->res);
972 return;
973 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300974
Ed Tanous002d39b2022-05-31 08:59:27 -0700975 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700976 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300977}
978
979/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300980 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530981 *
982 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530983 *
984 * @return None.
985 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300986
987inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530988{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700989 sdbusplus::asio::getProperty<std::string>(
990 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
991 "/xyz/openbmc_project/control/host0/boot",
992 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800993 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700994 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700995 if (ec)
996 {
997 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
998 messages::internalError(aResp->res);
999 return;
1000 }
1001
1002 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
1003
1004 aResp->res
1005 .jsonValue["Boot"]
1006 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
1007 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
1008
1009 if (bootModeStr !=
1010 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1011 {
1012 auto rfMode = dbusToRfBootMode(bootModeStr);
1013 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301014 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001015 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1016 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301017 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001018 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001019 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301020}
1021
1022/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001023 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301024 *
1025 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026 *
1027 * @return None.
1028 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029
1030inline void
1031 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301032{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001033 sdbusplus::asio::getProperty<std::string>(
1034 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1035 "/xyz/openbmc_project/control/host0/boot",
1036 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001037 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001038 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001039 if (ec)
1040 {
1041 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001042 if (ec.value() == boost::asio::error::host_unreachable)
1043 {
1044 return;
1045 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001046 messages::internalError(aResp->res);
1047 return;
1048 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301049
Ed Tanous002d39b2022-05-31 08:59:27 -07001050 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301051
Ed Tanous002d39b2022-05-31 08:59:27 -07001052 auto rfSource = dbusToRfBootSource(bootSourceStr);
1053 if (!rfSource.empty())
1054 {
1055 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1056 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001057
Ed Tanous002d39b2022-05-31 08:59:27 -07001058 // Get BootMode as BootSourceOverrideTarget is constructed
1059 // from both BootSource and BootMode
1060 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001061 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301062}
1063
1064/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001065 * @brief This functions abstracts all the logic behind getting a
1066 * "BootSourceOverrideEnabled" property from an overall boot override enable
1067 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301068 *
1069 * @param[in] aResp Shared pointer for generating response message.
1070 *
1071 * @return None.
1072 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301073
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074inline void
1075 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1076 const bool bootOverrideEnableSetting)
1077{
1078 if (!bootOverrideEnableSetting)
1079 {
1080 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1081 return;
1082 }
1083
1084 // If boot source override is enabled, we need to check 'one_time'
1085 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001086 sdbusplus::asio::getProperty<bool>(
1087 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1088 "/xyz/openbmc_project/control/host0/boot/one_time",
1089 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001090 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001091 if (ec)
1092 {
1093 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1094 messages::internalError(aResp->res);
1095 return;
1096 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301097
Ed Tanous002d39b2022-05-31 08:59:27 -07001098 if (oneTimeSetting)
1099 {
1100 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1101 }
1102 else
1103 {
1104 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1105 "Continuous";
1106 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001107 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301108}
1109
1110/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001111 * @brief Retrieves boot override enable over DBUS
1112 *
1113 * @param[in] aResp Shared pointer for generating response message.
1114 *
1115 * @return None.
1116 */
1117
1118inline void
1119 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1120{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001121 sdbusplus::asio::getProperty<bool>(
1122 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1123 "/xyz/openbmc_project/control/host0/boot",
1124 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001125 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001126 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001127 if (ec)
1128 {
1129 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001130 if (ec.value() == boost::asio::error::host_unreachable)
1131 {
1132 return;
1133 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001134 messages::internalError(aResp->res);
1135 return;
1136 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001137
Ed Tanous002d39b2022-05-31 08:59:27 -07001138 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001139 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001140}
1141
1142/**
1143 * @brief Retrieves boot source override properties
1144 *
1145 * @param[in] aResp Shared pointer for generating response message.
1146 *
1147 * @return None.
1148 */
1149inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1150{
1151 BMCWEB_LOG_DEBUG << "Get boot information.";
1152
1153 getBootOverrideSource(aResp);
1154 getBootOverrideType(aResp);
1155 getBootOverrideEnable(aResp);
1156}
1157
1158/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001159 * @brief Retrieves the Last Reset Time
1160 *
1161 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1162 * and power off. Even though this is the "system" Redfish object look at the
1163 * chassis D-Bus interface for the LastStateChangeTime since this has the
1164 * last power operation time.
1165 *
1166 * @param[in] aResp Shared pointer for generating response message.
1167 *
1168 * @return None.
1169 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001170inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001171{
1172 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1173
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001174 sdbusplus::asio::getProperty<uint64_t>(
1175 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1176 "/xyz/openbmc_project/state/chassis0",
1177 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001178 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001179 if (ec)
1180 {
1181 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1182 return;
1183 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001184
Ed Tanous002d39b2022-05-31 08:59:27 -07001185 // LastStateChangeTime is epoch time, in milliseconds
1186 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1187 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001188
Ed Tanous002d39b2022-05-31 08:59:27 -07001189 // Convert to ISO 8601 standard
1190 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001191 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001192 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001193}
1194
1195/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001196 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1197 *
1198 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1199 * corresponding property "AttemptsLeft" that keeps track of the amount of
1200 * automatic retry attempts left are hosted in phosphor-state-manager through
1201 * dbus.
1202 *
1203 * @param[in] aResp Shared pointer for generating response message.
1204 *
1205 * @return None.
1206 */
1207inline void
1208 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1209{
1210 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1211
1212 sdbusplus::asio::getAllProperties(
1213 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1214 "/xyz/openbmc_project/state/host0",
1215 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1216 [aResp{aResp}](const boost::system::error_code& ec,
1217 const dbus::utility::DBusPropertiesMap& propertiesList) {
1218 if (ec)
1219 {
1220 if (ec.value() != EBADR)
1221 {
1222 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1223 messages::internalError(aResp->res);
1224 }
1225 return;
1226 }
1227
1228 const uint32_t* attemptsLeft = nullptr;
1229 const uint32_t* retryAttempts = nullptr;
1230
1231 const bool success = sdbusplus::unpackPropertiesNoThrow(
1232 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1233 attemptsLeft, "RetryAttempts", retryAttempts);
1234
1235 if (!success)
1236 {
1237 messages::internalError(aResp->res);
1238 return;
1239 }
1240
1241 if (attemptsLeft != nullptr)
1242 {
1243 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1244 *attemptsLeft;
1245 }
1246
1247 if (retryAttempts != nullptr)
1248 {
1249 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1250 *retryAttempts;
1251 }
1252 });
1253}
1254
1255/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001256 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1257 *
1258 * @param[in] aResp Shared pointer for generating response message.
1259 *
1260 * @return None.
1261 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001262inline void
1263 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001264{
1265 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1266
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001267 sdbusplus::asio::getProperty<bool>(
1268 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1269 "/xyz/openbmc_project/control/host0/auto_reboot",
1270 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001271 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001272 if (ec)
1273 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001274 if (ec.value() != EBADR)
1275 {
1276 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1277 messages::internalError(aResp->res);
1278 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001279 return;
1280 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001281
Ed Tanous002d39b2022-05-31 08:59:27 -07001282 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1283 if (autoRebootEnabled)
1284 {
1285 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1286 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001287 }
1288 else
1289 {
1290 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1291 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001292 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001293
Ed Tanous002d39b2022-05-31 08:59:27 -07001294 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1295 // and RetryAttempts. OpenBMC only supports Disabled and
1296 // RetryAttempts.
1297 aResp->res.jsonValue["Boot"]
1298 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1299 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001300 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001301}
1302
1303/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001304 * @brief Sets RetryAttempts
1305 *
1306 * @param[in] aResp Shared pointer for generating response message.
1307 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1308 *
1309 *@return None.
1310 */
1311
1312inline void
1313 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1314 const uint32_t retryAttempts)
1315{
1316 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1317 crow::connections::systemBus->async_method_call(
1318 [aResp](const boost::system::error_code& ec) {
1319 if (ec)
1320 {
1321 BMCWEB_LOG_ERROR
1322 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1323 messages::internalError(aResp->res);
1324 return;
1325 }
1326 },
1327 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1328 "org.freedesktop.DBus.Properties", "Set",
1329 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1330 std::variant<uint32_t>(retryAttempts));
1331}
1332
1333/**
George Liuc6a620f2020-04-10 17:18:11 +08001334 * @brief Retrieves power restore policy over DBUS.
1335 *
1336 * @param[in] aResp Shared pointer for generating response message.
1337 *
1338 * @return None.
1339 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001340inline void
1341 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001342{
1343 BMCWEB_LOG_DEBUG << "Get power restore policy";
1344
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001345 sdbusplus::asio::getProperty<std::string>(
1346 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1347 "/xyz/openbmc_project/control/host0/power_restore_policy",
1348 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001349 [aResp](const boost::system::error_code& ec,
1350 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001351 if (ec)
1352 {
1353 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1354 return;
1355 }
George Liuc6a620f2020-04-10 17:18:11 +08001356
Ed Tanous002d39b2022-05-31 08:59:27 -07001357 const boost::container::flat_map<std::string, std::string> policyMaps = {
1358 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1359 "AlwaysOn"},
1360 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1361 "AlwaysOff"},
1362 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1363 "LastState"},
1364 // Return `AlwaysOff` when power restore policy set to "None"
1365 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1366 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001367
Ed Tanous002d39b2022-05-31 08:59:27 -07001368 auto policyMapsIt = policyMaps.find(policy);
1369 if (policyMapsIt == policyMaps.end())
1370 {
1371 messages::internalError(aResp->res);
1372 return;
1373 }
George Liuc6a620f2020-04-10 17:18:11 +08001374
Ed Tanous002d39b2022-05-31 08:59:27 -07001375 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001376 });
George Liuc6a620f2020-04-10 17:18:11 +08001377}
1378
1379/**
Ali Ahmed19817712021-06-29 17:01:52 -05001380 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1381 * TPM is required for booting the host.
1382 *
1383 * @param[in] aResp Shared pointer for generating response message.
1384 *
1385 * @return None.
1386 */
1387inline void getTrustedModuleRequiredToBoot(
1388 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1389{
1390 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001391 constexpr std::array<std::string_view, 1> interfaces = {
1392 "xyz.openbmc_project.Control.TPM.Policy"};
1393 dbus::utility::getSubTree(
1394 "/", 0, interfaces,
1395 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001396 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001397 if (ec)
1398 {
1399 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1400 << ec;
1401 // This is an optional D-Bus object so just return if
1402 // error occurs
1403 return;
1404 }
1405 if (subtree.empty())
1406 {
1407 // As noted above, this is an optional interface so just return
1408 // if there is no instance found
1409 return;
1410 }
1411
1412 /* When there is more than one TPMEnable object... */
1413 if (subtree.size() > 1)
1414 {
1415 BMCWEB_LOG_DEBUG
1416 << "DBUS response has more than 1 TPM Enable object:"
1417 << subtree.size();
1418 // Throw an internal Error and return
1419 messages::internalError(aResp->res);
1420 return;
1421 }
1422
1423 // Make sure the Dbus response map has a service and objectPath
1424 // field
1425 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1426 {
1427 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1428 messages::internalError(aResp->res);
1429 return;
1430 }
1431
1432 const std::string& path = subtree[0].first;
1433 const std::string& serv = subtree[0].second.begin()->first;
1434
1435 // Valid TPM Enable object found, now reading the current value
1436 sdbusplus::asio::getProperty<bool>(
1437 *crow::connections::systemBus, serv, path,
1438 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001439 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001440 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001441 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001442 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001443 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001444 messages::internalError(aResp->res);
1445 return;
1446 }
1447
Ed Tanous002d39b2022-05-31 08:59:27 -07001448 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001449 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001450 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1451 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001452 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001453 else
1454 {
1455 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1456 "Disabled";
1457 }
1458 });
George Liue99073f2022-12-09 11:06:16 +08001459 });
Ali Ahmed19817712021-06-29 17:01:52 -05001460}
1461
1462/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001463 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1464 * TPM is required for booting the host.
1465 *
1466 * @param[in] aResp Shared pointer for generating response message.
1467 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1468 *
1469 * @return None.
1470 */
1471inline void setTrustedModuleRequiredToBoot(
1472 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1473{
1474 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001475 constexpr std::array<std::string_view, 1> interfaces = {
1476 "xyz.openbmc_project.Control.TPM.Policy"};
1477 dbus::utility::getSubTree(
1478 "/", 0, interfaces,
1479 [aResp,
1480 tpmRequired](const boost::system::error_code& ec,
1481 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001482 if (ec)
1483 {
1484 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1485 << ec;
1486 messages::internalError(aResp->res);
1487 return;
1488 }
1489 if (subtree.empty())
1490 {
1491 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1492 "TrustedModuleRequiredToBoot");
1493 return;
1494 }
1495
1496 /* When there is more than one TPMEnable object... */
1497 if (subtree.size() > 1)
1498 {
1499 BMCWEB_LOG_DEBUG
1500 << "DBUS response has more than 1 TPM Enable object:"
1501 << subtree.size();
1502 // Throw an internal Error and return
1503 messages::internalError(aResp->res);
1504 return;
1505 }
1506
1507 // Make sure the Dbus response map has a service and objectPath
1508 // field
1509 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1510 {
1511 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1512 messages::internalError(aResp->res);
1513 return;
1514 }
1515
1516 const std::string& path = subtree[0].first;
1517 const std::string& serv = subtree[0].second.begin()->first;
1518
1519 if (serv.empty())
1520 {
1521 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1522 messages::internalError(aResp->res);
1523 return;
1524 }
1525
1526 // Valid TPM Enable object found, now setting the value
1527 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001528 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001529 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001530 {
1531 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001532 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001533 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001534 messages::internalError(aResp->res);
1535 return;
1536 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001537 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1538 },
1539 serv, path, "org.freedesktop.DBus.Properties", "Set",
1540 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1541 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001542 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001543}
1544
1545/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301546 * @brief Sets boot properties into DBUS object(s).
1547 *
1548 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001549 * @param[in] bootType The boot type to set.
1550 * @return Integer error code.
1551 */
1552inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001553 const std::optional<std::string>& bootType)
1554{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001555 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001556
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001557 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001558 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001559 return;
1560 }
1561
1562 // Source target specified
1563 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1564 // Figure out which DBUS interface and property to use
1565 if (*bootType == "Legacy")
1566 {
1567 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1568 }
1569 else if (*bootType == "UEFI")
1570 {
1571 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1572 }
1573 else
1574 {
1575 BMCWEB_LOG_DEBUG << "Invalid property value for "
1576 "BootSourceOverrideMode: "
1577 << *bootType;
1578 messages::propertyValueNotInList(aResp->res, *bootType,
1579 "BootSourceOverrideMode");
1580 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001581 }
1582
1583 // Act on validated parameters
1584 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1585
1586 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001587 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001588 if (ec)
1589 {
1590 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1591 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001592 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001593 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001594 return;
1595 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001596 messages::internalError(aResp->res);
1597 return;
1598 }
1599 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001600 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001601 "xyz.openbmc_project.Settings",
1602 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001603 "org.freedesktop.DBus.Properties", "Set",
1604 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001605 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001606}
1607
1608/**
1609 * @brief Sets boot properties into DBUS object(s).
1610 *
1611 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001612 * @param[in] bootType The boot type to set.
1613 * @return Integer error code.
1614 */
1615inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1616 const std::optional<std::string>& bootEnable)
1617{
1618 if (!bootEnable)
1619 {
1620 return;
1621 }
1622 // Source target specified
1623 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1624
1625 bool bootOverrideEnable = false;
1626 bool bootOverridePersistent = false;
1627 // Figure out which DBUS interface and property to use
1628 if (*bootEnable == "Disabled")
1629 {
1630 bootOverrideEnable = false;
1631 }
1632 else if (*bootEnable == "Once")
1633 {
1634 bootOverrideEnable = true;
1635 bootOverridePersistent = false;
1636 }
1637 else if (*bootEnable == "Continuous")
1638 {
1639 bootOverrideEnable = true;
1640 bootOverridePersistent = true;
1641 }
1642 else
1643 {
George Liu0fda0f12021-11-16 10:06:17 +08001644 BMCWEB_LOG_DEBUG
1645 << "Invalid property value for BootSourceOverrideEnabled: "
1646 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001647 messages::propertyValueNotInList(aResp->res, *bootEnable,
1648 "BootSourceOverrideEnabled");
1649 return;
1650 }
1651
1652 // Act on validated parameters
1653 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1654
1655 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001656 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001657 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001658 {
Ed Tanous8a592812022-06-04 09:06:59 -07001659 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001660 messages::internalError(aResp->res);
1661 return;
1662 }
1663 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001664 },
1665 "xyz.openbmc_project.Settings",
1666 "/xyz/openbmc_project/control/host0/boot",
1667 "org.freedesktop.DBus.Properties", "Set",
1668 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001669 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001670
1671 if (!bootOverrideEnable)
1672 {
1673 return;
1674 }
1675
1676 // In case boot override is enabled we need to set correct value for the
1677 // 'one_time' enable DBus interface
1678 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1679 << bootOverridePersistent;
1680
1681 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001682 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001683 if (ec)
1684 {
1685 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1686 messages::internalError(aResp->res);
1687 return;
1688 }
1689 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690 },
1691 "xyz.openbmc_project.Settings",
1692 "/xyz/openbmc_project/control/host0/boot/one_time",
1693 "org.freedesktop.DBus.Properties", "Set",
1694 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001695 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001696}
1697
1698/**
1699 * @brief Sets boot properties into DBUS object(s).
1700 *
1701 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301702 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301703 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001704 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301705 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001706inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001707 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301708{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001709 std::string bootSourceStr;
1710 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001711
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001712 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301713 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001714 return;
1715 }
1716
1717 // Source target specified
1718 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1719 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001720 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1721 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001722 {
1723 BMCWEB_LOG_DEBUG
1724 << "Invalid property value for BootSourceOverrideTarget: "
1725 << *bootSource;
1726 messages::propertyValueNotInList(aResp->res, *bootSource,
1727 "BootSourceTargetOverride");
1728 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001729 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301730
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001731 // Act on validated parameters
1732 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1733 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001734
1735 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001736 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001737 if (ec)
1738 {
1739 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1740 messages::internalError(aResp->res);
1741 return;
1742 }
1743 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001744 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001745 "xyz.openbmc_project.Settings",
1746 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001747 "org.freedesktop.DBus.Properties", "Set",
1748 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001749 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001750
1751 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001752 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001753 if (ec)
1754 {
1755 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1756 messages::internalError(aResp->res);
1757 return;
1758 }
1759 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001760 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001761 "xyz.openbmc_project.Settings",
1762 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001763 "org.freedesktop.DBus.Properties", "Set",
1764 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001765 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001766}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001767
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001768/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001769 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301770 *
1771 * @param[in] aResp Shared pointer for generating response message.
1772 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001773 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301774 * @param[in] bootEnable The boot override enable from incoming RF request.
1775 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001776 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301777 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001778
1779inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1780 const std::optional<std::string>& bootSource,
1781 const std::optional<std::string>& bootType,
1782 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301783{
1784 BMCWEB_LOG_DEBUG << "Set boot information.";
1785
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001786 setBootModeOrSource(aResp, bootSource);
1787 setBootType(aResp, bootType);
1788 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301789}
1790
George Liuc6a620f2020-04-10 17:18:11 +08001791/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001792 * @brief Sets AssetTag
1793 *
1794 * @param[in] aResp Shared pointer for generating response message.
1795 * @param[in] assetTag "AssetTag" from request.
1796 *
1797 * @return None.
1798 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001799inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001800 const std::string& assetTag)
1801{
George Liue99073f2022-12-09 11:06:16 +08001802 constexpr std::array<std::string_view, 1> interfaces = {
1803 "xyz.openbmc_project.Inventory.Item.System"};
1804 dbus::utility::getSubTree(
1805 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001806 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001807 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001808 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001809 if (ec)
1810 {
1811 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1812 messages::internalError(aResp->res);
1813 return;
1814 }
1815 if (subtree.empty())
1816 {
1817 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1818 messages::internalError(aResp->res);
1819 return;
1820 }
1821 // Assume only 1 system D-Bus object
1822 // Throw an error if there is more than 1
1823 if (subtree.size() > 1)
1824 {
1825 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1826 messages::internalError(aResp->res);
1827 return;
1828 }
1829 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1830 {
1831 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1832 messages::internalError(aResp->res);
1833 return;
1834 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001835
Ed Tanous002d39b2022-05-31 08:59:27 -07001836 const std::string& path = subtree[0].first;
1837 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001838
Ed Tanous002d39b2022-05-31 08:59:27 -07001839 if (service.empty())
1840 {
1841 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1842 messages::internalError(aResp->res);
1843 return;
1844 }
1845
1846 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001847 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001848 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001849 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001850 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1851 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001852 messages::internalError(aResp->res);
1853 return;
1854 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001855 },
1856 service, path, "org.freedesktop.DBus.Properties", "Set",
1857 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1858 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001859 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001860}
1861
1862/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001863 * @brief Sets automaticRetry (Auto Reboot)
1864 *
1865 * @param[in] aResp Shared pointer for generating response message.
1866 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1867 *
1868 * @return None.
1869 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001870inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001871 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001872{
1873 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1874
1875 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001876 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001877
1878 if (automaticRetryConfig == "Disabled")
1879 {
1880 autoRebootEnabled = false;
1881 }
1882 else if (automaticRetryConfig == "RetryAttempts")
1883 {
1884 autoRebootEnabled = true;
1885 }
1886 else
1887 {
George Liu0fda0f12021-11-16 10:06:17 +08001888 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001889 << automaticRetryConfig;
1890 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1891 "AutomaticRetryConfig");
1892 return;
1893 }
1894
1895 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001896 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001897 if (ec)
1898 {
1899 messages::internalError(aResp->res);
1900 return;
1901 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001902 },
1903 "xyz.openbmc_project.Settings",
1904 "/xyz/openbmc_project/control/host0/auto_reboot",
1905 "org.freedesktop.DBus.Properties", "Set",
1906 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001907 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001908}
1909
1910/**
George Liuc6a620f2020-04-10 17:18:11 +08001911 * @brief Sets power restore policy properties.
1912 *
1913 * @param[in] aResp Shared pointer for generating response message.
1914 * @param[in] policy power restore policy properties from request.
1915 *
1916 * @return None.
1917 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001918inline void
1919 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1920 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001921{
1922 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1923
1924 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001925 {"AlwaysOn",
1926 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1927 {"AlwaysOff",
1928 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1929 {"LastState",
1930 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001931
1932 std::string powerRestorPolicy;
1933
Gunnar Mills4e69c902021-01-05 19:50:11 -06001934 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001935 if (policyMapsIt == policyMaps.end())
1936 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001937 messages::propertyValueNotInList(aResp->res, policy,
1938 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001939 return;
1940 }
1941
1942 powerRestorPolicy = policyMapsIt->second;
1943
1944 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001945 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001946 if (ec)
1947 {
1948 messages::internalError(aResp->res);
1949 return;
1950 }
George Liuc6a620f2020-04-10 17:18:11 +08001951 },
1952 "xyz.openbmc_project.Settings",
1953 "/xyz/openbmc_project/control/host0/power_restore_policy",
1954 "org.freedesktop.DBus.Properties", "Set",
1955 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001956 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001957}
1958
AppaRao Pulia6349912019-10-18 17:16:08 +05301959#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1960/**
1961 * @brief Retrieves provisioning status
1962 *
1963 * @param[in] aResp Shared pointer for completing asynchronous calls.
1964 *
1965 * @return None.
1966 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001967inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301968{
1969 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001970 sdbusplus::asio::getAllProperties(
1971 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1972 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001973 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001974 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001975 nlohmann::json& oemPFR =
1976 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1977 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1978 "#OemComputerSystem.OpenBmc";
1979 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001980
Ed Tanous002d39b2022-05-31 08:59:27 -07001981 if (ec)
1982 {
1983 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1984 // not an error, don't have to have the interface
1985 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1986 return;
1987 }
1988
1989 const bool* provState = nullptr;
1990 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001991
1992 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001993 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1994 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001995
1996 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001997 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001998 messages::internalError(aResp->res);
1999 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002000 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302001
Ed Tanous002d39b2022-05-31 08:59:27 -07002002 if ((provState == nullptr) || (lockState == nullptr))
2003 {
2004 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
2005 messages::internalError(aResp->res);
2006 return;
2007 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302008
Ed Tanous002d39b2022-05-31 08:59:27 -07002009 if (*provState == true)
2010 {
2011 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05302012 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002013 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302014 }
2015 else
2016 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002017 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302018 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002019 }
2020 else
2021 {
2022 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2023 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002024 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302025}
2026#endif
2027
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302028/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002029 * @brief Translate the PowerMode to a response message.
2030 *
2031 * @param[in] aResp Shared pointer for generating response message.
2032 * @param[in] modeValue PowerMode value to be translated
2033 *
2034 * @return None.
2035 */
2036inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2037 const std::string& modeValue)
2038{
George Liu0fda0f12021-11-16 10:06:17 +08002039 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002040 {
2041 aResp->res.jsonValue["PowerMode"] = "Static";
2042 }
George Liu0fda0f12021-11-16 10:06:17 +08002043 else if (
2044 modeValue ==
2045 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002046 {
2047 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2048 }
George Liu0fda0f12021-11-16 10:06:17 +08002049 else if (modeValue ==
2050 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002051 {
2052 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2053 }
George Liu0fda0f12021-11-16 10:06:17 +08002054 else if (modeValue ==
2055 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002056 {
2057 aResp->res.jsonValue["PowerMode"] = "OEM";
2058 }
2059 else
2060 {
2061 // Any other values would be invalid
2062 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2063 messages::internalError(aResp->res);
2064 }
2065}
2066
2067/**
2068 * @brief Retrieves system power mode
2069 *
2070 * @param[in] aResp Shared pointer for generating response message.
2071 *
2072 * @return None.
2073 */
2074inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2075{
2076 BMCWEB_LOG_DEBUG << "Get power mode.";
2077
2078 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002079 constexpr std::array<std::string_view, 1> interfaces = {
2080 "xyz.openbmc_project.Control.Power.Mode"};
2081 dbus::utility::getSubTree(
2082 "/", 0, interfaces,
2083 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002084 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002085 if (ec)
2086 {
2087 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2088 << ec;
2089 // This is an optional D-Bus object so just return if
2090 // error occurs
2091 return;
2092 }
2093 if (subtree.empty())
2094 {
2095 // As noted above, this is an optional interface so just return
2096 // if there is no instance found
2097 return;
2098 }
2099 if (subtree.size() > 1)
2100 {
2101 // More then one PowerMode object is not supported and is an
2102 // error
2103 BMCWEB_LOG_DEBUG
2104 << "Found more than 1 system D-Bus Power.Mode objects: "
2105 << subtree.size();
2106 messages::internalError(aResp->res);
2107 return;
2108 }
2109 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2110 {
2111 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2112 messages::internalError(aResp->res);
2113 return;
2114 }
2115 const std::string& path = subtree[0].first;
2116 const std::string& service = subtree[0].second.begin()->first;
2117 if (service.empty())
2118 {
2119 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2120 messages::internalError(aResp->res);
2121 return;
2122 }
2123 // Valid Power Mode object found, now read the current value
2124 sdbusplus::asio::getProperty<std::string>(
2125 *crow::connections::systemBus, service, path,
2126 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002127 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002128 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002129 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002130 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002131 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002132 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002133 messages::internalError(aResp->res);
2134 return;
2135 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002136
Ed Tanous002d39b2022-05-31 08:59:27 -07002137 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2138 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002139
Ed Tanous002d39b2022-05-31 08:59:27 -07002140 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2141 translatePowerMode(aResp, pmode);
2142 });
George Liue99073f2022-12-09 11:06:16 +08002143 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002144}
2145
2146/**
2147 * @brief Validate the specified mode is valid and return the PowerMode
2148 * name associated with that string
2149 *
2150 * @param[in] aResp Shared pointer for generating response message.
2151 * @param[in] modeString String representing the desired PowerMode
2152 *
2153 * @return PowerMode value or empty string if mode is not valid
2154 */
2155inline std::string
2156 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2157 const std::string& modeString)
2158{
2159 std::string mode;
2160
2161 if (modeString == "Static")
2162 {
2163 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2164 }
2165 else if (modeString == "MaximumPerformance")
2166 {
George Liu0fda0f12021-11-16 10:06:17 +08002167 mode =
2168 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002169 }
2170 else if (modeString == "PowerSaving")
2171 {
2172 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2173 }
2174 else
2175 {
2176 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2177 }
2178 return mode;
2179}
2180
2181/**
2182 * @brief Sets system power mode.
2183 *
2184 * @param[in] aResp Shared pointer for generating response message.
2185 * @param[in] pmode System power mode from request.
2186 *
2187 * @return None.
2188 */
2189inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2190 const std::string& pmode)
2191{
2192 BMCWEB_LOG_DEBUG << "Set power mode.";
2193
2194 std::string powerMode = validatePowerMode(aResp, pmode);
2195 if (powerMode.empty())
2196 {
2197 return;
2198 }
2199
2200 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002201 constexpr std::array<std::string_view, 1> interfaces = {
2202 "xyz.openbmc_project.Control.Power.Mode"};
2203 dbus::utility::getSubTree(
2204 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002205 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002206 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002207 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002208 if (ec)
2209 {
2210 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2211 << ec;
2212 // This is an optional D-Bus object, but user attempted to patch
2213 messages::internalError(aResp->res);
2214 return;
2215 }
2216 if (subtree.empty())
2217 {
2218 // This is an optional D-Bus object, but user attempted to patch
2219 messages::resourceNotFound(aResp->res, "ComputerSystem",
2220 "PowerMode");
2221 return;
2222 }
2223 if (subtree.size() > 1)
2224 {
2225 // More then one PowerMode object is not supported and is an
2226 // error
2227 BMCWEB_LOG_DEBUG
2228 << "Found more than 1 system D-Bus Power.Mode objects: "
2229 << subtree.size();
2230 messages::internalError(aResp->res);
2231 return;
2232 }
2233 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2234 {
2235 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2236 messages::internalError(aResp->res);
2237 return;
2238 }
2239 const std::string& path = subtree[0].first;
2240 const std::string& service = subtree[0].second.begin()->first;
2241 if (service.empty())
2242 {
2243 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2244 messages::internalError(aResp->res);
2245 return;
2246 }
2247
2248 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2249 << path;
2250
2251 // Set the Power Mode property
2252 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002253 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002254 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002255 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002256 messages::internalError(aResp->res);
2257 return;
2258 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002259 },
2260 service, path, "org.freedesktop.DBus.Properties", "Set",
2261 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2262 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002263 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002264}
2265
2266/**
Yong Li51709ff2019-09-30 14:13:04 +08002267 * @brief Translates watchdog timeout action DBUS property value to redfish.
2268 *
2269 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2270 *
2271 * @return Returns as a string, the timeout action in Redfish terms. If
2272 * translation cannot be done, returns an empty string.
2273 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002274inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002275{
2276 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2277 {
2278 return "None";
2279 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002280 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002281 {
2282 return "ResetSystem";
2283 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002284 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002285 {
2286 return "PowerDown";
2287 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002288 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002289 {
2290 return "PowerCycle";
2291 }
2292
2293 return "";
2294}
2295
2296/**
Yong Lic45f0082019-10-10 14:19:01 +08002297 *@brief Translates timeout action from Redfish to DBUS property value.
2298 *
2299 *@param[in] rfAction The timeout action in Redfish.
2300 *
2301 *@return Returns as a string, the time_out action as expected by DBUS.
2302 *If translation cannot be done, returns an empty string.
2303 */
2304
Ed Tanous23a21a12020-07-25 04:45:05 +00002305inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002306{
2307 if (rfAction == "None")
2308 {
2309 return "xyz.openbmc_project.State.Watchdog.Action.None";
2310 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002311 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002312 {
2313 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2314 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002315 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002316 {
2317 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2318 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002319 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002320 {
2321 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2322 }
2323
2324 return "";
2325}
2326
2327/**
Yong Li51709ff2019-09-30 14:13:04 +08002328 * @brief Retrieves host watchdog timer properties over DBUS
2329 *
2330 * @param[in] aResp Shared pointer for completing asynchronous calls.
2331 *
2332 * @return None.
2333 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002334inline void
2335 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002336{
2337 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002338 sdbusplus::asio::getAllProperties(
2339 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2340 "/xyz/openbmc_project/watchdog/host0",
2341 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002342 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002343 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002344 if (ec)
2345 {
2346 // watchdog service is stopped
2347 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2348 return;
2349 }
2350
2351 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2352
2353 nlohmann::json& hostWatchdogTimer =
2354 aResp->res.jsonValue["HostWatchdogTimer"];
2355
2356 // watchdog service is running/enabled
2357 hostWatchdogTimer["Status"]["State"] = "Enabled";
2358
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002359 const bool* enabled = nullptr;
2360 const std::string* expireAction = nullptr;
2361
2362 const bool success = sdbusplus::unpackPropertiesNoThrow(
2363 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2364 "ExpireAction", expireAction);
2365
2366 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002367 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002368 messages::internalError(aResp->res);
2369 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002370 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002371
2372 if (enabled != nullptr)
2373 {
2374 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2375 }
2376
2377 if (expireAction != nullptr)
2378 {
2379 std::string action = dbusToRfWatchdogAction(*expireAction);
2380 if (action.empty())
2381 {
2382 messages::internalError(aResp->res);
2383 return;
2384 }
2385 hostWatchdogTimer["TimeoutAction"] = action;
2386 }
2387 });
Yong Li51709ff2019-09-30 14:13:04 +08002388}
2389
2390/**
Yong Lic45f0082019-10-10 14:19:01 +08002391 * @brief Sets Host WatchDog Timer properties.
2392 *
2393 * @param[in] aResp Shared pointer for generating response message.
2394 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2395 * RF request.
2396 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2397 *
2398 * @return None.
2399 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002400inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002401 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002402 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002403{
2404 BMCWEB_LOG_DEBUG << "Set host watchdog";
2405
2406 if (wdtTimeOutAction)
2407 {
2408 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2409 // check if TimeOut Action is Valid
2410 if (wdtTimeOutActStr.empty())
2411 {
2412 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2413 << *wdtTimeOutAction;
2414 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2415 "TimeoutAction");
2416 return;
2417 }
2418
2419 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002420 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002421 if (ec)
2422 {
2423 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2424 messages::internalError(aResp->res);
2425 return;
2426 }
Yong Lic45f0082019-10-10 14:19:01 +08002427 },
2428 "xyz.openbmc_project.Watchdog",
2429 "/xyz/openbmc_project/watchdog/host0",
2430 "org.freedesktop.DBus.Properties", "Set",
2431 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002432 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002433 }
2434
2435 if (wdtEnable)
2436 {
2437 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002438 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002439 if (ec)
2440 {
2441 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2442 messages::internalError(aResp->res);
2443 return;
2444 }
Yong Lic45f0082019-10-10 14:19:01 +08002445 },
2446 "xyz.openbmc_project.Watchdog",
2447 "/xyz/openbmc_project/watchdog/host0",
2448 "org.freedesktop.DBus.Properties", "Set",
2449 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002450 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002451 }
2452}
2453
Chris Cain37bbf982021-09-20 10:53:09 -05002454/**
2455 * @brief Parse the Idle Power Saver properties into json
2456 *
2457 * @param[in] aResp Shared pointer for completing asynchronous calls.
2458 * @param[in] properties IPS property data from DBus.
2459 *
2460 * @return true if successful
2461 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002462inline bool
2463 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2464 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002465{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002466 const bool* enabled = nullptr;
2467 const uint8_t* enterUtilizationPercent = nullptr;
2468 const uint64_t* enterDwellTime = nullptr;
2469 const uint8_t* exitUtilizationPercent = nullptr;
2470 const uint64_t* exitDwellTime = nullptr;
2471
2472 const bool success = sdbusplus::unpackPropertiesNoThrow(
2473 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002474 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2475 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2476 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002477
2478 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002479 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002480 return false;
2481 }
2482
2483 if (enabled != nullptr)
2484 {
2485 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2486 }
2487
2488 if (enterUtilizationPercent != nullptr)
2489 {
2490 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2491 *enterUtilizationPercent;
2492 }
2493
2494 if (enterDwellTime != nullptr)
2495 {
2496 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2497 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2498 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2499 .count();
2500 }
2501
2502 if (exitUtilizationPercent != nullptr)
2503 {
2504 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2505 *exitUtilizationPercent;
2506 }
2507
2508 if (exitDwellTime != nullptr)
2509 {
2510 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2511 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2512 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2513 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002514 }
2515
2516 return true;
2517}
2518
2519/**
2520 * @brief Retrieves host watchdog timer properties over DBUS
2521 *
2522 * @param[in] aResp Shared pointer for completing asynchronous calls.
2523 *
2524 * @return None.
2525 */
2526inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2527{
2528 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2529
2530 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002531 constexpr std::array<std::string_view, 1> interfaces = {
2532 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2533 dbus::utility::getSubTree(
2534 "/", 0, interfaces,
2535 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002536 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002537 if (ec)
2538 {
2539 BMCWEB_LOG_DEBUG
2540 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2541 << ec;
2542 messages::internalError(aResp->res);
2543 return;
2544 }
2545 if (subtree.empty())
2546 {
2547 // This is an optional interface so just return
2548 // if there is no instance found
2549 BMCWEB_LOG_DEBUG << "No instances found";
2550 return;
2551 }
2552 if (subtree.size() > 1)
2553 {
2554 // More then one PowerIdlePowerSaver object is not supported and
2555 // is an error
2556 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2557 "Power.IdlePowerSaver objects: "
2558 << subtree.size();
2559 messages::internalError(aResp->res);
2560 return;
2561 }
2562 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2563 {
2564 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2565 messages::internalError(aResp->res);
2566 return;
2567 }
2568 const std::string& path = subtree[0].first;
2569 const std::string& service = subtree[0].second.begin()->first;
2570 if (service.empty())
2571 {
2572 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2573 messages::internalError(aResp->res);
2574 return;
2575 }
2576
2577 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002578 sdbusplus::asio::getAllProperties(
2579 *crow::connections::systemBus, service, path,
2580 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002581 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002582 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002583 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002584 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002585 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002586 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002587 messages::internalError(aResp->res);
2588 return;
2589 }
2590
Ed Tanous002d39b2022-05-31 08:59:27 -07002591 if (!parseIpsProperties(aResp, properties))
2592 {
2593 messages::internalError(aResp->res);
2594 return;
2595 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002596 });
George Liue99073f2022-12-09 11:06:16 +08002597 });
Chris Cain37bbf982021-09-20 10:53:09 -05002598
2599 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2600}
2601
2602/**
2603 * @brief Sets Idle Power Saver properties.
2604 *
2605 * @param[in] aResp Shared pointer for generating response message.
2606 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2607 * RF request.
2608 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2609 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2610 * before entering idle state.
2611 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2612 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2613 * before exiting idle state
2614 *
2615 * @return None.
2616 */
2617inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2618 const std::optional<bool> ipsEnable,
2619 const std::optional<uint8_t> ipsEnterUtil,
2620 const std::optional<uint64_t> ipsEnterTime,
2621 const std::optional<uint8_t> ipsExitUtil,
2622 const std::optional<uint64_t> ipsExitTime)
2623{
2624 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2625
2626 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002627 constexpr std::array<std::string_view, 1> interfaces = {
2628 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2629 dbus::utility::getSubTree(
2630 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002631 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002632 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002633 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002634 if (ec)
2635 {
2636 BMCWEB_LOG_DEBUG
2637 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2638 << ec;
2639 messages::internalError(aResp->res);
2640 return;
2641 }
2642 if (subtree.empty())
2643 {
2644 // This is an optional D-Bus object, but user attempted to patch
2645 messages::resourceNotFound(aResp->res, "ComputerSystem",
2646 "IdlePowerSaver");
2647 return;
2648 }
2649 if (subtree.size() > 1)
2650 {
2651 // More then one PowerIdlePowerSaver object is not supported and
2652 // is an error
2653 BMCWEB_LOG_DEBUG
2654 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2655 << subtree.size();
2656 messages::internalError(aResp->res);
2657 return;
2658 }
2659 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2660 {
2661 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2662 messages::internalError(aResp->res);
2663 return;
2664 }
2665 const std::string& path = subtree[0].first;
2666 const std::string& service = subtree[0].second.begin()->first;
2667 if (service.empty())
2668 {
2669 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2670 messages::internalError(aResp->res);
2671 return;
2672 }
Chris Cain37bbf982021-09-20 10:53:09 -05002673
Ed Tanous002d39b2022-05-31 08:59:27 -07002674 // Valid Power IdlePowerSaver object found, now set any values that
2675 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002676
Ed Tanous002d39b2022-05-31 08:59:27 -07002677 if (ipsEnable)
2678 {
2679 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002680 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002681 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002682 {
Ed Tanous8a592812022-06-04 09:06:59 -07002683 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002684 messages::internalError(aResp->res);
2685 return;
2686 }
2687 },
2688 service, path, "org.freedesktop.DBus.Properties", "Set",
2689 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2690 dbus::utility::DbusVariantType(*ipsEnable));
2691 }
2692 if (ipsEnterUtil)
2693 {
2694 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002695 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002696 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002697 {
Ed Tanous8a592812022-06-04 09:06:59 -07002698 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002699 messages::internalError(aResp->res);
2700 return;
2701 }
2702 },
2703 service, path, "org.freedesktop.DBus.Properties", "Set",
2704 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2705 "EnterUtilizationPercent",
2706 dbus::utility::DbusVariantType(*ipsEnterUtil));
2707 }
2708 if (ipsEnterTime)
2709 {
2710 // Convert from seconds into milliseconds for DBus
2711 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2712 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002713 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002714 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002715 {
Ed Tanous8a592812022-06-04 09:06:59 -07002716 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002717 messages::internalError(aResp->res);
2718 return;
2719 }
2720 },
2721 service, path, "org.freedesktop.DBus.Properties", "Set",
2722 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2723 "EnterDwellTime",
2724 dbus::utility::DbusVariantType(timeMilliseconds));
2725 }
2726 if (ipsExitUtil)
2727 {
2728 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002729 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002730 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002731 {
Ed Tanous8a592812022-06-04 09:06:59 -07002732 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002733 messages::internalError(aResp->res);
2734 return;
2735 }
2736 },
2737 service, path, "org.freedesktop.DBus.Properties", "Set",
2738 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2739 "ExitUtilizationPercent",
2740 dbus::utility::DbusVariantType(*ipsExitUtil));
2741 }
2742 if (ipsExitTime)
2743 {
2744 // Convert from seconds into milliseconds for DBus
2745 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2746 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002747 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002748 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002749 {
Ed Tanous8a592812022-06-04 09:06:59 -07002750 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002751 messages::internalError(aResp->res);
2752 return;
2753 }
2754 },
2755 service, path, "org.freedesktop.DBus.Properties", "Set",
2756 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2757 "ExitDwellTime",
2758 dbus::utility::DbusVariantType(timeMilliseconds));
2759 }
George Liue99073f2022-12-09 11:06:16 +08002760 });
Chris Cain37bbf982021-09-20 10:53:09 -05002761
2762 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2763}
2764
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002765inline void handleComputerSystemHead(
2766 crow::App& app, const crow::Request& req,
2767 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2768{
2769 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2770 {
2771 return;
2772 }
2773 asyncResp->res.addHeader(
2774 boost::beast::http::field::link,
2775 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2776}
2777
Yong Lic45f0082019-10-10 14:19:01 +08002778/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002779 * SystemsCollection derived class for delivering ComputerSystems Collection
2780 * Schema
2781 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002782inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002783{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002784 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002785 .privileges(redfish::privileges::headComputerSystemCollection)
2786 .methods(boost::beast::http::verb::head)(
2787 std::bind_front(handleComputerSystemHead, std::ref(app)));
2788
2789 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002790 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002791 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002792 [&app](const crow::Request& req,
2793 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002794 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002795 {
2796 return;
2797 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002798
2799 asyncResp->res.addHeader(
2800 boost::beast::http::field::link,
2801 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002802 asyncResp->res.jsonValue["@odata.type"] =
2803 "#ComputerSystemCollection.ComputerSystemCollection";
2804 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2805 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002806
Ed Tanous002d39b2022-05-31 08:59:27 -07002807 sdbusplus::asio::getProperty<std::string>(
2808 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2809 "/xyz/openbmc_project/network/hypervisor",
2810 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002811 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002812 const std::string& /*hostName*/) {
2813 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2814 ifaceArray = nlohmann::json::array();
2815 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002816
Ed Tanous002d39b2022-05-31 08:59:27 -07002817 nlohmann::json::object_t system;
2818 system["@odata.id"] = "/redfish/v1/Systems/system";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002819 ifaceArray.emplace_back(std::move(system));
Ed Tanous002d39b2022-05-31 08:59:27 -07002820 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002821 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002822 {
2823 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2824 nlohmann::json::object_t hypervisor;
2825 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002826 ifaceArray.emplace_back(std::move(hypervisor));
Ed Tanous002d39b2022-05-31 08:59:27 -07002827 count = ifaceArray.size();
2828 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002829 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002830 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831}
Sunitha Harish462023a2020-02-19 08:34:59 -06002832
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002833/**
2834 * Function transceives data with dbus directly.
2835 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002836inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002837{
Patrick Williams89492a12023-05-10 07:51:34 -05002838 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2839 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2840 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002841 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002842 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843
2844 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002845 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002846 if (ec)
2847 {
2848 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2849 messages::internalError(asyncResp->res);
2850 return;
2851 }
2852 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002853 },
2854 serviceName, objectPath, interfaceName, method);
2855}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002856
2857/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002858 * SystemActionsReset class supports handle POST method for Reset action.
2859 * The class retrieves and sends data directly to D-Bus.
2860 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002861inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002862{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002863 /**
2864 * Function handles POST method request.
2865 * Analyzes POST body message before sends Reset request data to D-Bus.
2866 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002867 BMCWEB_ROUTE(app,
2868 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002869 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002870 .methods(boost::beast::http::verb::post)(
2871 [&app](const crow::Request& req,
2872 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002873 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002874 {
2875 return;
2876 }
2877 std::string resetType;
2878 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2879 resetType))
2880 {
2881 return;
2882 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002883
Ed Tanous002d39b2022-05-31 08:59:27 -07002884 // Get the command and host vs. chassis
2885 std::string command;
2886 bool hostCommand = true;
2887 if ((resetType == "On") || (resetType == "ForceOn"))
2888 {
2889 command = "xyz.openbmc_project.State.Host.Transition.On";
2890 hostCommand = true;
2891 }
2892 else if (resetType == "ForceOff")
2893 {
2894 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2895 hostCommand = false;
2896 }
2897 else if (resetType == "ForceRestart")
2898 {
2899 command =
2900 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2901 hostCommand = true;
2902 }
2903 else if (resetType == "GracefulShutdown")
2904 {
2905 command = "xyz.openbmc_project.State.Host.Transition.Off";
2906 hostCommand = true;
2907 }
2908 else if (resetType == "GracefulRestart")
2909 {
2910 command =
2911 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2912 hostCommand = true;
2913 }
2914 else if (resetType == "PowerCycle")
2915 {
2916 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2917 hostCommand = true;
2918 }
2919 else if (resetType == "Nmi")
2920 {
2921 doNMI(asyncResp);
2922 return;
2923 }
2924 else
2925 {
2926 messages::actionParameterUnknown(asyncResp->res, "Reset",
2927 resetType);
2928 return;
2929 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002930
Ed Tanous002d39b2022-05-31 08:59:27 -07002931 if (hostCommand)
2932 {
2933 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002934 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002935 if (ec)
2936 {
2937 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2938 if (ec.value() == boost::asio::error::invalid_argument)
2939 {
2940 messages::actionParameterNotSupported(
2941 asyncResp->res, resetType, "Reset");
2942 }
2943 else
2944 {
2945 messages::internalError(asyncResp->res);
2946 }
2947 return;
2948 }
2949 messages::success(asyncResp->res);
2950 },
2951 "xyz.openbmc_project.State.Host",
2952 "/xyz/openbmc_project/state/host0",
2953 "org.freedesktop.DBus.Properties", "Set",
2954 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2955 dbus::utility::DbusVariantType{command});
2956 }
2957 else
2958 {
2959 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002960 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002961 if (ec)
2962 {
2963 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2964 if (ec.value() == boost::asio::error::invalid_argument)
2965 {
2966 messages::actionParameterNotSupported(
2967 asyncResp->res, resetType, "Reset");
2968 }
2969 else
2970 {
2971 messages::internalError(asyncResp->res);
2972 }
2973 return;
2974 }
2975 messages::success(asyncResp->res);
2976 },
2977 "xyz.openbmc_project.State.Chassis",
2978 "/xyz/openbmc_project/state/chassis0",
2979 "org.freedesktop.DBus.Properties", "Set",
2980 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2981 dbus::utility::DbusVariantType{command});
2982 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002983 });
2984}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002985
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002986inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002987 App& app, const crow::Request& req,
2988 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2989{
2990 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2991 {
2992 return;
2993 }
2994
2995 asyncResp->res.addHeader(
2996 boost::beast::http::field::link,
2997 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2998}
2999
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003000inline void afterPortRequest(
3001 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3002 const boost::system::error_code& ec,
3003 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3004{
3005 if (ec)
3006 {
3007 messages::internalError(asyncResp->res);
3008 return;
3009 }
3010 for (const auto& data : socketData)
3011 {
3012 const std::string& socketPath = get<0>(data);
3013 const std::string& protocolName = get<1>(data);
3014 bool isProtocolEnabled = get<2>(data);
3015 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3016 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3017 // need to retrieve port number for
3018 // obmc-console-ssh service
3019 if (protocolName == "SSH")
3020 {
3021 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003022 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003023 int portNumber) {
3024 if (ec1)
3025 {
3026 messages::internalError(asyncResp->res);
3027 return;
3028 }
3029 nlohmann::json& dataJson1 =
3030 asyncResp->res.jsonValue["SerialConsole"];
3031 dataJson1[protocolName]["Port"] = portNumber;
3032 });
3033 }
3034 }
3035}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003036/**
Ed Tanous66173382018-08-15 18:20:59 -07003037 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003038 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003040{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003041 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
3042 .privileges(redfish::privileges::headComputerSystem)
3043 .methods(boost::beast::http::verb::head)(
3044 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07003045 /**
3046 * Functions triggers appropriate requests on DBus
3047 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003048 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003049 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003050 .methods(boost::beast::http::verb::get)(
3051 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003052 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3053 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003054 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003055 {
3056 return;
3057 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003058
3059 if (systemName == "hypervisor")
3060 {
3061 handleHypervisorSystemGet(asyncResp);
3062 return;
3063 }
3064
Ed Tanous22d268c2022-05-19 09:39:07 -07003065 if (systemName != "system")
3066 {
3067 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3068 systemName);
3069 return;
3070 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003071 asyncResp->res.addHeader(
3072 boost::beast::http::field::link,
3073 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003074 asyncResp->res.jsonValue["@odata.type"] =
3075 "#ComputerSystem.v1_16_0.ComputerSystem";
3076 asyncResp->res.jsonValue["Name"] = "system";
3077 asyncResp->res.jsonValue["Id"] = "system";
3078 asyncResp->res.jsonValue["SystemType"] = "Physical";
3079 asyncResp->res.jsonValue["Description"] = "Computer System";
3080 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -05003081 if constexpr (bmcwebEnableProcMemStatus)
3082 {
3083 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3084 "Disabled";
3085 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3086 "Disabled";
3087 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -05003088 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3089 uint64_t(0);
Ed Tanous002d39b2022-05-31 08:59:27 -07003090 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003091
Ed Tanous002d39b2022-05-31 08:59:27 -07003092 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3093 "/redfish/v1/Systems/system/Processors";
3094 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3095 "/redfish/v1/Systems/system/Memory";
3096 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3097 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003098 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3099 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003100
Ed Tanous002d39b2022-05-31 08:59:27 -07003101 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3102 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3103 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3104 ["@Redfish.ActionInfo"] =
3105 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003106
Ed Tanous002d39b2022-05-31 08:59:27 -07003107 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3108 "/redfish/v1/Systems/system/LogServices";
3109 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3110 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003111
Ed Tanous002d39b2022-05-31 08:59:27 -07003112 nlohmann::json::array_t managedBy;
3113 nlohmann::json& manager = managedBy.emplace_back();
3114 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3115 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3116 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3117 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003118
Ed Tanous002d39b2022-05-31 08:59:27 -07003119 // Fill in SerialConsole info
3120 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3121 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3122 true;
Ed Tanous14766872022-03-15 10:44:42 -07003123
Ed Tanous002d39b2022-05-31 08:59:27 -07003124 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3125 true;
3126 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3127 asyncResp->res
3128 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3129 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003130 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3131 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003132
3133#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003134 // Fill in GraphicalConsole info
3135 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3136 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3137 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003138 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3139 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003140
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003141#endif // BMCWEB_ENABLE_KVM
James Feistb49ac872019-05-21 15:12:01 -07003142
Ed Tanous002d39b2022-05-31 08:59:27 -07003143 auto health = std::make_shared<HealthPopulate>(asyncResp);
Willy Tu13451e32023-05-24 16:08:18 -07003144 if constexpr (bmcwebEnableHealthPopulate)
3145 {
3146 constexpr std::array<std::string_view, 4> inventoryForSystems{
3147 "xyz.openbmc_project.Inventory.Item.Dimm",
3148 "xyz.openbmc_project.Inventory.Item.Cpu",
3149 "xyz.openbmc_project.Inventory.Item.Drive",
3150 "xyz.openbmc_project.Inventory.Item.StorageController"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003151
Willy Tu13451e32023-05-24 16:08:18 -07003152 dbus::utility::getSubTreePaths(
3153 "/", 0, inventoryForSystems,
3154 [health](const boost::system::error_code& ec,
3155 const std::vector<std::string>& resp) {
3156 if (ec)
3157 {
3158 // no inventory
3159 return;
3160 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003161
Willy Tu13451e32023-05-24 16:08:18 -07003162 health->inventory = resp;
3163 });
3164 health->populate();
3165 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003166
Ed Tanous002d39b2022-05-31 08:59:27 -07003167 getMainChassisId(asyncResp,
3168 [](const std::string& chassisId,
3169 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3170 nlohmann::json::array_t chassisArray;
3171 nlohmann::json& chassis = chassisArray.emplace_back();
Ed Tanousef4c65b2023-04-24 15:28:50 -07003172 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3173 chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003174 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3175 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003176
Ed Tanous002d39b2022-05-31 08:59:27 -07003177 getLocationIndicatorActive(asyncResp);
3178 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3179 getIndicatorLedState(asyncResp);
3180 getComputerSystem(asyncResp, health);
3181 getHostState(asyncResp);
3182 getBootProperties(asyncResp);
3183 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003184 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003185 getPCIeDeviceList(asyncResp, "PCIeDevices");
3186 getHostWatchdogTimer(asyncResp);
3187 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003188 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003189 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003190#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003191 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003192#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003193 getTrustedModuleRequiredToBoot(asyncResp);
3194 getPowerMode(asyncResp);
3195 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003196 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003197
Ed Tanous22d268c2022-05-19 09:39:07 -07003198 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003199 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003200 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003201 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003202 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3203 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003204 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003205 {
3206 return;
3207 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003208 if (systemName != "system")
3209 {
3210 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3211 systemName);
3212 return;
3213 }
3214
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003215 asyncResp->res.addHeader(
3216 boost::beast::http::field::link,
3217 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3218
Ed Tanous002d39b2022-05-31 08:59:27 -07003219 std::optional<bool> locationIndicatorActive;
3220 std::optional<std::string> indicatorLed;
3221 std::optional<std::string> assetTag;
3222 std::optional<std::string> powerRestorePolicy;
3223 std::optional<std::string> powerMode;
3224 std::optional<bool> wdtEnable;
3225 std::optional<std::string> wdtTimeOutAction;
3226 std::optional<std::string> bootSource;
3227 std::optional<std::string> bootType;
3228 std::optional<std::string> bootEnable;
3229 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003230 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003231 std::optional<bool> bootTrustedModuleRequired;
3232 std::optional<bool> ipsEnable;
3233 std::optional<uint8_t> ipsEnterUtil;
3234 std::optional<uint64_t> ipsEnterTime;
3235 std::optional<uint8_t> ipsExitUtil;
3236 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003237
Ed Tanous002d39b2022-05-31 08:59:27 -07003238 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003239 if (!json_util::readJsonPatch(
3240 req, asyncResp->res,
3241 "IndicatorLED", indicatorLed,
3242 "LocationIndicatorActive", locationIndicatorActive,
3243 "AssetTag", assetTag,
3244 "PowerRestorePolicy", powerRestorePolicy,
3245 "PowerMode", powerMode,
3246 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3247 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3248 "Boot/BootSourceOverrideTarget", bootSource,
3249 "Boot/BootSourceOverrideMode", bootType,
3250 "Boot/BootSourceOverrideEnabled", bootEnable,
3251 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003252 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003253 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3254 "IdlePowerSaver/Enabled", ipsEnable,
3255 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3256 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3257 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3258 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3259 {
3260 return;
3261 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003262 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003263
Ed Tanous002d39b2022-05-31 08:59:27 -07003264 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003265
Ed Tanous002d39b2022-05-31 08:59:27 -07003266 if (assetTag)
3267 {
3268 setAssetTag(asyncResp, *assetTag);
3269 }
James Feistb49ac872019-05-21 15:12:01 -07003270
Ed Tanous002d39b2022-05-31 08:59:27 -07003271 if (wdtEnable || wdtTimeOutAction)
3272 {
3273 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3274 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003275
Ed Tanous002d39b2022-05-31 08:59:27 -07003276 if (bootSource || bootType || bootEnable)
3277 {
3278 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3279 }
3280 if (bootAutomaticRetry)
3281 {
3282 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3283 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003284
Corey Hardesty797d5da2022-04-26 17:54:52 +08003285 if (bootAutomaticRetryAttempts)
3286 {
3287 setAutomaticRetryAttempts(asyncResp,
3288 bootAutomaticRetryAttempts.value());
3289 }
3290
Ed Tanous002d39b2022-05-31 08:59:27 -07003291 if (bootTrustedModuleRequired)
3292 {
3293 setTrustedModuleRequiredToBoot(asyncResp,
3294 *bootTrustedModuleRequired);
3295 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003296
Ed Tanous002d39b2022-05-31 08:59:27 -07003297 if (locationIndicatorActive)
3298 {
3299 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3300 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003301
Ed Tanous002d39b2022-05-31 08:59:27 -07003302 // TODO (Gunnar): Remove IndicatorLED after enough time has
3303 // passed
3304 if (indicatorLed)
3305 {
3306 setIndicatorLedState(asyncResp, *indicatorLed);
3307 asyncResp->res.addHeader(boost::beast::http::field::warning,
3308 "299 - \"IndicatorLED is deprecated. Use "
3309 "LocationIndicatorActive instead.\"");
3310 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003311
Ed Tanous002d39b2022-05-31 08:59:27 -07003312 if (powerRestorePolicy)
3313 {
3314 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3315 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003316
Ed Tanous002d39b2022-05-31 08:59:27 -07003317 if (powerMode)
3318 {
3319 setPowerMode(asyncResp, *powerMode);
3320 }
Chris Cain37bbf982021-09-20 10:53:09 -05003321
Ed Tanous002d39b2022-05-31 08:59:27 -07003322 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3323 ipsExitTime)
3324 {
3325 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3326 ipsExitUtil, ipsExitTime);
3327 }
3328 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003329}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303330
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003331inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003332 crow::App& app, const crow::Request& req,
3333 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3334{
3335 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3336 {
3337 return;
3338 }
3339 asyncResp->res.addHeader(
3340 boost::beast::http::field::link,
3341 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3342}
3343
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303344/**
3345 * SystemResetActionInfo derived class for delivering Computer Systems
3346 * ResetType AllowableValues using ResetInfo schema.
3347 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003348inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303349{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003350 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3351 .privileges(redfish::privileges::headActionInfo)
3352 .methods(boost::beast::http::verb::head)(std::bind_front(
3353 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303354 /**
3355 * Functions triggers appropriate requests on DBus
3356 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003357 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003358 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003359 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003360 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003361 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3362 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003363 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003364 {
3365 return;
3366 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003367
3368 if (systemName == "hypervisor")
3369 {
3370 handleHypervisorResetActionGet(asyncResp);
3371 return;
3372 }
3373
Ed Tanous22d268c2022-05-19 09:39:07 -07003374 if (systemName != "system")
3375 {
3376 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3377 systemName);
3378 return;
3379 }
3380
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003381 asyncResp->res.addHeader(
3382 boost::beast::http::field::link,
3383 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003384
Ed Tanous002d39b2022-05-31 08:59:27 -07003385 asyncResp->res.jsonValue["@odata.id"] =
3386 "/redfish/v1/Systems/system/ResetActionInfo";
3387 asyncResp->res.jsonValue["@odata.type"] =
3388 "#ActionInfo.v1_1_2.ActionInfo";
3389 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3390 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003391
3392 nlohmann::json::array_t parameters;
3393 nlohmann::json::object_t parameter;
3394
3395 parameter["Name"] = "ResetType";
3396 parameter["Required"] = true;
3397 parameter["DataType"] = "String";
3398 nlohmann::json::array_t allowableValues;
3399 allowableValues.emplace_back("On");
3400 allowableValues.emplace_back("ForceOff");
3401 allowableValues.emplace_back("ForceOn");
3402 allowableValues.emplace_back("ForceRestart");
3403 allowableValues.emplace_back("GracefulRestart");
3404 allowableValues.emplace_back("GracefulShutdown");
3405 allowableValues.emplace_back("PowerCycle");
3406 allowableValues.emplace_back("Nmi");
3407 parameter["AllowableValues"] = std::move(allowableValues);
3408 parameters.emplace_back(std::move(parameter));
3409
3410 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003411 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003412}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003413} // namespace redfish