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