blob: c9d31d176408924fe6e7ad64af71d89fc7e9ffab [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070019#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070021#include "health.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060022#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080023#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080024#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070025#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080026#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080027#include "registries/privilege_registry.hpp"
28#include "utils/dbus_utils.hpp"
29#include "utils/json_utils.hpp"
30#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070031#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080032
Ed Tanous9712f8a2018-09-21 13:38:49 -070033#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080034#include <boost/system/error_code.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070035#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020036#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050037
George Liu7a1dbc42022-12-07 16:03:22 +080038#include <array>
39#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080040#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020041
Ed Tanous1abe55e2018-09-05 08:30:59 -070042namespace redfish
43{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020044
Abhishek Patel5c3e9272021-06-24 10:11:33 -050045const static std::array<std::pair<std::string_view, std::string_view>, 2>
46 protocolToDBusForSystems{
47 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
48
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049/**
50 * @brief Updates the Functional State of DIMMs
51 *
52 * @param[in] aResp Shared pointer for completing asynchronous calls
53 * @param[in] dimmState Dimm's Functional state, true/false
54 *
55 * @return None.
56 */
zhanghch058d1b46d2021-04-01 11:18:24 +080057inline void
58 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070059 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050060{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070061 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050062
Gunnar Mills4e0453b2020-07-08 14:00:30 -050063 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050064 // Update STATE only if previous State was DISABLED and current Dimm is
65 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070066 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050067 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
68 if (prevMemSummary == "Disabled")
69 {
Ed Tanouse05aec52022-01-25 10:28:56 -080070 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050071 {
72 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
73 "Enabled";
74 }
75 }
76}
77
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050078/*
79 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
80 *
81 * @param[in] aResp Shared pointer for completing asynchronous calls
82 * @param[in] cpuPresenceState CPU present or not
83 *
84 * @return None.
85 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070086inline void
87 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
88 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050089{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070090 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091
Ed Tanous55f79e62022-01-25 11:26:16 -080092 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050094 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080095 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080096 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050097 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080098 if (procCountPtr != nullptr)
99 {
100 // shouldn't be possible to be nullptr
101 *procCountPtr += 1;
102 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500104}
105
106/*
107 * @brief Update "ProcessorSummary" "Status" "State" based on
108 * CPU Functional State
109 *
110 * @param[in] aResp Shared pointer for completing asynchronous calls
111 * @param[in] cpuFunctionalState is CPU functional true/false
112 *
113 * @return None.
114 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700115inline void
116 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
117 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700119 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500120
Ed Tanous02cad962022-06-30 16:50:15 -0700121 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500122 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
123
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500124 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500125 // Update STATE only if previous State was Non_Functional and current CPU is
126 // Functional.
127 if (prevProcState == "Disabled")
128 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800129 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500130 {
131 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
132 "Enabled";
133 }
134 }
135}
136
Ali Ahmed382d6472021-09-03 16:53:53 -0500137inline void getProcessorProperties(
138 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
139 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
140 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500141{
142
143 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{
188
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800189 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500190 const bool cpuPresenceCheck) {
191 if (ec3)
192 {
193 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
194 return;
195 }
196 modifyCpuPresenceState(aResp, cpuPresenceCheck);
197 };
198
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800199 auto getCpuFunctionalState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500200 const bool cpuFunctionalCheck) {
201 if (ec3)
202 {
203 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
204 return;
205 }
206 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
207 };
208
209 // Get the Presence of CPU
210 sdbusplus::asio::getProperty<bool>(
211 *crow::connections::systemBus, service, path,
212 "xyz.openbmc_project.Inventory.Item", "Present",
213 std::move(getCpuPresenceState));
214
215 // Get the Functional State
216 sdbusplus::asio::getProperty<bool>(
217 *crow::connections::systemBus, service, path,
218 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
219 std::move(getCpuFunctionalState));
220
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200221 sdbusplus::asio::getAllProperties(
222 *crow::connections::systemBus, service, path,
223 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500224 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800225 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800226 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700227 if (ec2)
228 {
229 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
230 messages::internalError(aResp->res);
231 return;
232 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500233 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200234 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500235}
236
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500237/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700238 * @brief Retrieves computer system properties over dbus
239 *
240 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500241 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700242 *
243 * @return None.
244 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700245inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800246 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700247 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700248{
Ed Tanous6c34de42018-08-29 13:37:36 -0700249 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800250 constexpr std::array<std::string_view, 5> interfaces = {
251 "xyz.openbmc_project.Inventory.Decorator.Asset",
252 "xyz.openbmc_project.Inventory.Item.Cpu",
253 "xyz.openbmc_project.Inventory.Item.Dimm",
254 "xyz.openbmc_project.Inventory.Item.System",
255 "xyz.openbmc_project.Common.UUID",
256 };
257 dbus::utility::getSubTree(
258 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800259 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800260 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800261 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700262 if (ec)
263 {
264 BMCWEB_LOG_DEBUG << "DBUS response error";
265 messages::internalError(aResp->res);
266 return;
267 }
268 // Iterate over all retrieved ObjectPaths.
269 for (const std::pair<
270 std::string,
271 std::vector<std::pair<std::string, std::vector<std::string>>>>&
272 object : subtree)
273 {
274 const std::string& path = object.first;
275 BMCWEB_LOG_DEBUG << "Got path: " << path;
276 const std::vector<std::pair<std::string, std::vector<std::string>>>&
277 connectionNames = object.second;
278 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700279 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700280 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700281 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700282
283 auto memoryHealth = std::make_shared<HealthPopulate>(
284 aResp, "/MemorySummary/Status"_json_pointer);
285
286 auto cpuHealth = std::make_shared<HealthPopulate>(
287 aResp, "/ProcessorSummary/Status"_json_pointer);
288
289 systemHealth->children.emplace_back(memoryHealth);
290 systemHealth->children.emplace_back(cpuHealth);
291
292 // This is not system, so check if it's cpu, dimm, UUID or
293 // BiosVer
294 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700295 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700296 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700297 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700298 if (interfaceName ==
299 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700300 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700301 BMCWEB_LOG_DEBUG
302 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500303
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200304 sdbusplus::asio::getAllProperties(
305 *crow::connections::systemBus, connection.first,
306 path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanous002d39b2022-05-31 08:59:27 -0700307 [aResp, service{connection.first},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800308 path](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700309 const dbus::utility::DBusPropertiesMap&
310 properties) {
311 if (ec2)
312 {
313 BMCWEB_LOG_ERROR << "DBUS response error "
314 << ec2;
315 messages::internalError(aResp->res);
316 return;
317 }
318 BMCWEB_LOG_DEBUG << "Got " << properties.size()
319 << " Dimm properties.";
320
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200321 if (properties.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700322 {
323 sdbusplus::asio::getProperty<bool>(
324 *crow::connections::systemBus, service,
325 path,
326 "xyz.openbmc_project.State."
327 "Decorator.OperationalStatus",
328 "Functional",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800329 [aResp](
330 const boost::system::error_code& ec3,
331 bool dimmState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700332 if (ec3)
333 {
334 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000335 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800336 return;
337 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700338 updateDimmProperties(aResp, dimmState);
339 });
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200340 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700341 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200342
343 const uint32_t* memorySizeInKB = nullptr;
344
345 const bool success =
346 sdbusplus::unpackPropertiesNoThrow(
347 dbus_utils::UnpackErrorPrinter(),
348 properties, "MemorySizeInKB",
349 memorySizeInKB);
350
351 if (!success)
352 {
353 messages::internalError(aResp->res);
354 return;
355 }
356
357 if (memorySizeInKB != nullptr)
358 {
359 nlohmann::json& totalMemory =
360 aResp->res
361 .jsonValue["MemorySummary"]
362 ["TotalSystemMemoryGiB"];
363 const uint64_t* preValue =
364 totalMemory.get_ptr<const uint64_t*>();
365 if (preValue == nullptr)
366 {
367 aResp->res
368 .jsonValue["MemorySummary"]
369 ["TotalSystemMemoryGiB"] =
370 *memorySizeInKB / (1024 * 1024);
371 }
372 else
373 {
374 aResp->res
375 .jsonValue["MemorySummary"]
376 ["TotalSystemMemoryGiB"] =
377 *memorySizeInKB / (1024 * 1024) +
378 *preValue;
379 }
380 aResp->res.jsonValue["MemorySummary"]["Status"]
381 ["State"] = "Enabled";
382 }
383 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700384
385 memoryHealth->inventory.emplace_back(path);
386 }
387 else if (interfaceName ==
388 "xyz.openbmc_project.Inventory.Item.Cpu")
389 {
390 BMCWEB_LOG_DEBUG
391 << "Found Cpu, now get its properties.";
392
393 getProcessorSummary(aResp, connection.first, path);
394
395 cpuHealth->inventory.emplace_back(path);
396 }
397 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
398 {
399 BMCWEB_LOG_DEBUG
400 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200401
402 sdbusplus::asio::getAllProperties(
403 *crow::connections::systemBus, connection.first,
404 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800405 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700406 const dbus::utility::DBusPropertiesMap&
407 properties) {
408 if (ec3)
409 {
410 BMCWEB_LOG_DEBUG << "DBUS response error "
411 << ec3;
412 messages::internalError(aResp->res);
413 return;
414 }
415 BMCWEB_LOG_DEBUG << "Got " << properties.size()
416 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700417
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200418 const std::string* uUID = nullptr;
419
420 const bool success =
421 sdbusplus::unpackPropertiesNoThrow(
422 dbus_utils::UnpackErrorPrinter(),
423 properties, "UUID", uUID);
424
425 if (!success)
426 {
427 messages::internalError(aResp->res);
428 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700429 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200430
431 if (uUID != nullptr)
432 {
433 std::string valueStr = *uUID;
434 if (valueStr.size() == 32)
435 {
436 valueStr.insert(8, 1, '-');
437 valueStr.insert(13, 1, '-');
438 valueStr.insert(18, 1, '-');
439 valueStr.insert(23, 1, '-');
440 }
441 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
442 aResp->res.jsonValue["UUID"] = valueStr;
443 }
444 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700445 }
446 else if (interfaceName ==
447 "xyz.openbmc_project.Inventory.Item.System")
448 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200449 sdbusplus::asio::getAllProperties(
450 *crow::connections::systemBus, connection.first,
451 path,
452 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800453 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700454 const dbus::utility::DBusPropertiesMap&
455 propertiesList) {
456 if (ec2)
457 {
458 // doesn't have to include this
459 // interface
460 return;
461 }
462 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
463 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200464
465 const std::string* partNumber = nullptr;
466 const std::string* serialNumber = nullptr;
467 const std::string* manufacturer = nullptr;
468 const std::string* model = nullptr;
469 const std::string* subModel = nullptr;
470
471 const bool success =
472 sdbusplus::unpackPropertiesNoThrow(
473 dbus_utils::UnpackErrorPrinter(),
474 propertiesList, "PartNumber", partNumber,
475 "SerialNumber", serialNumber,
476 "Manufacturer", manufacturer, "Model",
477 model, "SubModel", subModel);
478
479 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700480 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200481 messages::internalError(aResp->res);
482 return;
483 }
484
485 if (partNumber != nullptr)
486 {
487 aResp->res.jsonValue["PartNumber"] =
488 *partNumber;
489 }
490
491 if (serialNumber != nullptr)
492 {
493 aResp->res.jsonValue["SerialNumber"] =
494 *serialNumber;
495 }
496
497 if (manufacturer != nullptr)
498 {
499 aResp->res.jsonValue["Manufacturer"] =
500 *manufacturer;
501 }
502
503 if (model != nullptr)
504 {
505 aResp->res.jsonValue["Model"] = *model;
506 }
507
508 if (subModel != nullptr)
509 {
510 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700511 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500512
Ed Tanous002d39b2022-05-31 08:59:27 -0700513 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700514 sw_util::populateSoftwareInformation(
515 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700516 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200517 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700518
Ed Tanous002d39b2022-05-31 08:59:27 -0700519 sdbusplus::asio::getProperty<std::string>(
520 *crow::connections::systemBus, connection.first,
521 path,
522 "xyz.openbmc_project.Inventory.Decorator."
523 "AssetTag",
524 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800525 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700526 const std::string& value) {
527 if (ec2)
528 {
529 // doesn't have to include this
530 // interface
531 return;
532 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700533
Ed Tanous002d39b2022-05-31 08:59:27 -0700534 aResp->res.jsonValue["AssetTag"] = value;
535 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700536 }
537 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200538 break;
Ed Tanous6c34de42018-08-29 13:37:36 -0700539 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700540 }
Ed Tanous66173382018-08-15 18:20:59 -0700541 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700542}
543
544/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700545 * @brief Retrieves host state properties over dbus
546 *
547 * @param[in] aResp Shared pointer for completing asynchronous calls.
548 *
549 * @return None.
550 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800551inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700552{
553 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700554 sdbusplus::asio::getProperty<std::string>(
555 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
556 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
557 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800558 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700559 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700560 if (ec)
561 {
562 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700563 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700564 // Service not available, no error, just don't return
565 // host state info
566 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700567 return;
568 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700569 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
570 messages::internalError(aResp->res);
571 return;
572 }
Ed Tanous66173382018-08-15 18:20:59 -0700573
Ed Tanous002d39b2022-05-31 08:59:27 -0700574 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
575 // Verify Host State
576 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
577 {
578 aResp->res.jsonValue["PowerState"] = "On";
579 aResp->res.jsonValue["Status"]["State"] = "Enabled";
580 }
581 else if (hostState ==
582 "xyz.openbmc_project.State.Host.HostState.Quiesced")
583 {
584 aResp->res.jsonValue["PowerState"] = "On";
585 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
586 }
587 else if (hostState ==
588 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
589 {
590 aResp->res.jsonValue["PowerState"] = "On";
591 aResp->res.jsonValue["Status"]["State"] = "InTest";
592 }
593 else if (
594 hostState ==
595 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
596 {
597 aResp->res.jsonValue["PowerState"] = "PoweringOn";
598 aResp->res.jsonValue["Status"]["State"] = "Starting";
599 }
600 else if (hostState ==
601 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
602 {
603 aResp->res.jsonValue["PowerState"] = "PoweringOff";
604 aResp->res.jsonValue["Status"]["State"] = "Disabled";
605 }
606 else
607 {
608 aResp->res.jsonValue["PowerState"] = "Off";
609 aResp->res.jsonValue["Status"]["State"] = "Disabled";
610 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700611 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700612}
613
614/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500615 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530616 *
617 * @param[in] dbusSource The boot source in DBUS speak.
618 *
619 * @return Returns as a string, the boot source in Redfish terms. If translation
620 * cannot be done, returns an empty string.
621 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000622inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530623{
624 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
625 {
626 return "None";
627 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700628 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530629 {
630 return "Hdd";
631 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700632 if (dbusSource ==
633 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530634 {
635 return "Cd";
636 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700637 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530638 {
639 return "Pxe";
640 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700641 if (dbusSource ==
642 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700643 {
644 return "Usb";
645 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700646 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530647}
648
649/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300650 * @brief Translates boot type DBUS property value to redfish.
651 *
652 * @param[in] dbusType The boot type in DBUS speak.
653 *
654 * @return Returns as a string, the boot type in Redfish terms. If translation
655 * cannot be done, returns an empty string.
656 */
657inline std::string dbusToRfBootType(const std::string& dbusType)
658{
659 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
660 {
661 return "Legacy";
662 }
663 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
664 {
665 return "UEFI";
666 }
667 return "";
668}
669
670/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500671 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530672 *
673 * @param[in] dbusMode The boot mode in DBUS speak.
674 *
675 * @return Returns as a string, the boot mode in Redfish terms. If translation
676 * cannot be done, returns an empty string.
677 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000678inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530679{
680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
681 {
682 return "None";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685 {
686 return "Diags";
687 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700688 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530689 {
690 return "BiosSetup";
691 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700692 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530693}
694
695/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600696 * @brief Translates boot progress DBUS property value to redfish.
697 *
698 * @param[in] dbusBootProgress The boot progress in DBUS speak.
699 *
700 * @return Returns as a string, the boot progress in Redfish terms. If
701 * translation cannot be done, returns "None".
702 */
703inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
704{
705 // Now convert the D-Bus BootProgress to the appropriate Redfish
706 // enum
707 std::string rfBpLastState = "None";
708 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
709 "ProgressStages.Unspecified")
710 {
711 rfBpLastState = "None";
712 }
713 else if (dbusBootProgress ==
714 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
715 "PrimaryProcInit")
716 {
717 rfBpLastState = "PrimaryProcessorInitializationStarted";
718 }
719 else if (dbusBootProgress ==
720 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
721 "BusInit")
722 {
723 rfBpLastState = "BusInitializationStarted";
724 }
725 else if (dbusBootProgress ==
726 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
727 "MemoryInit")
728 {
729 rfBpLastState = "MemoryInitializationStarted";
730 }
731 else if (dbusBootProgress ==
732 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
733 "SecondaryProcInit")
734 {
735 rfBpLastState = "SecondaryProcessorInitializationStarted";
736 }
737 else if (dbusBootProgress ==
738 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
739 "PCIInit")
740 {
741 rfBpLastState = "PCIResourceConfigStarted";
742 }
743 else if (dbusBootProgress ==
744 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
745 "SystemSetup")
746 {
747 rfBpLastState = "SetupEntered";
748 }
749 else if (dbusBootProgress ==
750 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
751 "SystemInitComplete")
752 {
753 rfBpLastState = "SystemHardwareInitializationComplete";
754 }
755 else if (dbusBootProgress ==
756 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
757 "OSStart")
758 {
759 rfBpLastState = "OSBootStarted";
760 }
761 else if (dbusBootProgress ==
762 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
763 "OSRunning")
764 {
765 rfBpLastState = "OSRunning";
766 }
767 else
768 {
769 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
770 << dbusBootProgress;
771 // Just return the default
772 }
773 return rfBpLastState;
774}
775
776/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500777 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 *
779 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780 * @param[out] bootSource The DBus source
781 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530782 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800785inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500786 const std::string& rfSource,
787 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300789 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
790 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700791
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530792 if (rfSource == "None")
793 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530795 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700796 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530797 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700798 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
799 }
800 else if (rfSource == "Hdd")
801 {
802 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
803 }
804 else if (rfSource == "Diags")
805 {
806 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
807 }
808 else if (rfSource == "Cd")
809 {
810 bootSource =
811 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
812 }
813 else if (rfSource == "BiosSetup")
814 {
815 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530816 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700817 else if (rfSource == "Usb")
818 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700819 bootSource =
820 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700821 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530822 else
823 {
George Liu0fda0f12021-11-16 10:06:17 +0800824 BMCWEB_LOG_DEBUG
825 << "Invalid property value for BootSourceOverrideTarget: "
826 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700827 messages::propertyValueNotInList(aResp->res, rfSource,
828 "BootSourceTargetOverride");
829 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530830 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700831 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530832}
Ali Ahmed19817712021-06-29 17:01:52 -0500833
Andrew Geissler978b8802020-11-19 13:36:40 -0600834/**
835 * @brief Retrieves boot progress of the system
836 *
837 * @param[in] aResp Shared pointer for generating response message.
838 *
839 * @return None.
840 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800841inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600842{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700843 sdbusplus::asio::getProperty<std::string>(
844 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
845 "/xyz/openbmc_project/state/host0",
846 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800847 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700848 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700849 if (ec)
850 {
851 // BootProgress is an optional object so just do nothing if
852 // not found
853 return;
854 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600855
Ed Tanous002d39b2022-05-31 08:59:27 -0700856 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600857
Ed Tanous002d39b2022-05-31 08:59:27 -0700858 aResp->res.jsonValue["BootProgress"]["LastState"] =
859 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700860 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600861}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530862
863/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000864 * @brief Retrieves boot progress Last Update of the system
865 *
866 * @param[in] aResp Shared pointer for generating response message.
867 *
868 * @return None.
869 */
870inline void getBootProgressLastStateTime(
871 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
872{
873 sdbusplus::asio::getProperty<uint64_t>(
874 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
875 "/xyz/openbmc_project/state/host0",
876 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800877 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000878 const uint64_t lastStateTime) {
879 if (ec)
880 {
881 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
882 return;
883 }
884
885 // BootProgressLastUpdate is the last time the BootProgress property
886 // was updated. The time is the Epoch time, number of microseconds
887 // since 1 Jan 1970 00::00::00 UTC."
888 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
889 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
890
891 // Convert to ISO 8601 standard
892 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
893 redfish::time_utils::getDateTimeUintUs(lastStateTime);
894 });
895}
896
897/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300898 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300899 *
900 * @param[in] aResp Shared pointer for generating response message.
901 *
902 * @return None.
903 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300904
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300905inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300906{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700907 sdbusplus::asio::getProperty<std::string>(
908 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
909 "/xyz/openbmc_project/control/host0/boot",
910 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800911 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700912 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700913 if (ec)
914 {
915 // not an error, don't have to have the interface
916 return;
917 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918
Ed Tanous002d39b2022-05-31 08:59:27 -0700919 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300920
Ed Tanous002d39b2022-05-31 08:59:27 -0700921 aResp->res.jsonValue["Boot"]
922 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700923 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300924
Ed Tanous002d39b2022-05-31 08:59:27 -0700925 auto rfType = dbusToRfBootType(bootType);
926 if (rfType.empty())
927 {
928 messages::internalError(aResp->res);
929 return;
930 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300931
Ed Tanous002d39b2022-05-31 08:59:27 -0700932 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700933 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300934}
935
936/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300937 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938 *
939 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940 *
941 * @return None.
942 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943
944inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530945{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700946 sdbusplus::asio::getProperty<std::string>(
947 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
948 "/xyz/openbmc_project/control/host0/boot",
949 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800950 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700951 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700952 if (ec)
953 {
954 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
955 messages::internalError(aResp->res);
956 return;
957 }
958
959 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
960
961 aResp->res
962 .jsonValue["Boot"]
963 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
964 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
965
966 if (bootModeStr !=
967 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
968 {
969 auto rfMode = dbusToRfBootMode(bootModeStr);
970 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530971 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700972 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
973 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700975 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700976 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530977}
978
979/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300980 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530981 *
982 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530983 *
984 * @return None.
985 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300986
987inline void
988 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530989{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700990 sdbusplus::asio::getProperty<std::string>(
991 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
992 "/xyz/openbmc_project/control/host0/boot",
993 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800994 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700995 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700996 if (ec)
997 {
998 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000999 if (ec.value() == boost::asio::error::host_unreachable)
1000 {
1001 return;
1002 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001003 messages::internalError(aResp->res);
1004 return;
1005 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301006
Ed Tanous002d39b2022-05-31 08:59:27 -07001007 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008
Ed Tanous002d39b2022-05-31 08:59:27 -07001009 auto rfSource = dbusToRfBootSource(bootSourceStr);
1010 if (!rfSource.empty())
1011 {
1012 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1013 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001014
Ed Tanous002d39b2022-05-31 08:59:27 -07001015 // Get BootMode as BootSourceOverrideTarget is constructed
1016 // from both BootSource and BootMode
1017 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001018 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019}
1020
1021/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001022 * @brief This functions abstracts all the logic behind getting a
1023 * "BootSourceOverrideEnabled" property from an overall boot override enable
1024 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301025 *
1026 * @param[in] aResp Shared pointer for generating response message.
1027 *
1028 * @return None.
1029 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301030
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001031inline void
1032 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1033 const bool bootOverrideEnableSetting)
1034{
1035 if (!bootOverrideEnableSetting)
1036 {
1037 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1038 return;
1039 }
1040
1041 // If boot source override is enabled, we need to check 'one_time'
1042 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001043 sdbusplus::asio::getProperty<bool>(
1044 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1045 "/xyz/openbmc_project/control/host0/boot/one_time",
1046 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001047 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001048 if (ec)
1049 {
1050 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1051 messages::internalError(aResp->res);
1052 return;
1053 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301054
Ed Tanous002d39b2022-05-31 08:59:27 -07001055 if (oneTimeSetting)
1056 {
1057 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1058 }
1059 else
1060 {
1061 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1062 "Continuous";
1063 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001064 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301065}
1066
1067/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001068 * @brief Retrieves boot override enable over DBUS
1069 *
1070 * @param[in] aResp Shared pointer for generating response message.
1071 *
1072 * @return None.
1073 */
1074
1075inline void
1076 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1077{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001078 sdbusplus::asio::getProperty<bool>(
1079 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1080 "/xyz/openbmc_project/control/host0/boot",
1081 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001082 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001083 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001084 if (ec)
1085 {
1086 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001087 if (ec.value() == boost::asio::error::host_unreachable)
1088 {
1089 return;
1090 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001091 messages::internalError(aResp->res);
1092 return;
1093 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001094
Ed Tanous002d39b2022-05-31 08:59:27 -07001095 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001096 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001097}
1098
1099/**
1100 * @brief Retrieves boot source override properties
1101 *
1102 * @param[in] aResp Shared pointer for generating response message.
1103 *
1104 * @return None.
1105 */
1106inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1107{
1108 BMCWEB_LOG_DEBUG << "Get boot information.";
1109
1110 getBootOverrideSource(aResp);
1111 getBootOverrideType(aResp);
1112 getBootOverrideEnable(aResp);
1113}
1114
1115/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001116 * @brief Retrieves the Last Reset Time
1117 *
1118 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1119 * and power off. Even though this is the "system" Redfish object look at the
1120 * chassis D-Bus interface for the LastStateChangeTime since this has the
1121 * last power operation time.
1122 *
1123 * @param[in] aResp Shared pointer for generating response message.
1124 *
1125 * @return None.
1126 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001127inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001128{
1129 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1130
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001131 sdbusplus::asio::getProperty<uint64_t>(
1132 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1133 "/xyz/openbmc_project/state/chassis0",
1134 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001135 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001136 if (ec)
1137 {
1138 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1139 return;
1140 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001141
Ed Tanous002d39b2022-05-31 08:59:27 -07001142 // LastStateChangeTime is epoch time, in milliseconds
1143 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1144 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001145
Ed Tanous002d39b2022-05-31 08:59:27 -07001146 // Convert to ISO 8601 standard
1147 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001148 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001149 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001150}
1151
1152/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001153 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1154 *
1155 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1156 * corresponding property "AttemptsLeft" that keeps track of the amount of
1157 * automatic retry attempts left are hosted in phosphor-state-manager through
1158 * dbus.
1159 *
1160 * @param[in] aResp Shared pointer for generating response message.
1161 *
1162 * @return None.
1163 */
1164inline void
1165 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1166{
1167 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1168
1169 sdbusplus::asio::getAllProperties(
1170 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1171 "/xyz/openbmc_project/state/host0",
1172 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1173 [aResp{aResp}](const boost::system::error_code& ec,
1174 const dbus::utility::DBusPropertiesMap& propertiesList) {
1175 if (ec)
1176 {
1177 if (ec.value() != EBADR)
1178 {
1179 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1180 messages::internalError(aResp->res);
1181 }
1182 return;
1183 }
1184
1185 const uint32_t* attemptsLeft = nullptr;
1186 const uint32_t* retryAttempts = nullptr;
1187
1188 const bool success = sdbusplus::unpackPropertiesNoThrow(
1189 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1190 attemptsLeft, "RetryAttempts", retryAttempts);
1191
1192 if (!success)
1193 {
1194 messages::internalError(aResp->res);
1195 return;
1196 }
1197
1198 if (attemptsLeft != nullptr)
1199 {
1200 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1201 *attemptsLeft;
1202 }
1203
1204 if (retryAttempts != nullptr)
1205 {
1206 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1207 *retryAttempts;
1208 }
1209 });
1210}
1211
1212/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001213 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1214 *
1215 * @param[in] aResp Shared pointer for generating response message.
1216 *
1217 * @return None.
1218 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001219inline void
1220 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001221{
1222 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1223
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001224 sdbusplus::asio::getProperty<bool>(
1225 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1226 "/xyz/openbmc_project/control/host0/auto_reboot",
1227 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001228 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001229 if (ec)
1230 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001231 if (ec.value() != EBADR)
1232 {
1233 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1234 messages::internalError(aResp->res);
1235 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001236 return;
1237 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001238
Ed Tanous002d39b2022-05-31 08:59:27 -07001239 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1240 if (autoRebootEnabled)
1241 {
1242 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1243 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001244 }
1245 else
1246 {
1247 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1248 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001249 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001250
Ed Tanous002d39b2022-05-31 08:59:27 -07001251 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1252 // and RetryAttempts. OpenBMC only supports Disabled and
1253 // RetryAttempts.
1254 aResp->res.jsonValue["Boot"]
1255 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1256 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001257 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001258}
1259
1260/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001261 * @brief Sets RetryAttempts
1262 *
1263 * @param[in] aResp Shared pointer for generating response message.
1264 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1265 *
1266 *@return None.
1267 */
1268
1269inline void
1270 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1271 const uint32_t retryAttempts)
1272{
1273 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1274 crow::connections::systemBus->async_method_call(
1275 [aResp](const boost::system::error_code& ec) {
1276 if (ec)
1277 {
1278 BMCWEB_LOG_ERROR
1279 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1280 messages::internalError(aResp->res);
1281 return;
1282 }
1283 },
1284 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1285 "org.freedesktop.DBus.Properties", "Set",
1286 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1287 std::variant<uint32_t>(retryAttempts));
1288}
1289
1290/**
George Liuc6a620f2020-04-10 17:18:11 +08001291 * @brief Retrieves power restore policy over DBUS.
1292 *
1293 * @param[in] aResp Shared pointer for generating response message.
1294 *
1295 * @return None.
1296 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001297inline void
1298 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001299{
1300 BMCWEB_LOG_DEBUG << "Get power restore policy";
1301
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001302 sdbusplus::asio::getProperty<std::string>(
1303 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1304 "/xyz/openbmc_project/control/host0/power_restore_policy",
1305 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001306 [aResp](const boost::system::error_code& ec,
1307 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001308 if (ec)
1309 {
1310 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1311 return;
1312 }
George Liuc6a620f2020-04-10 17:18:11 +08001313
Ed Tanous002d39b2022-05-31 08:59:27 -07001314 const boost::container::flat_map<std::string, std::string> policyMaps = {
1315 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1316 "AlwaysOn"},
1317 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1318 "AlwaysOff"},
1319 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1320 "LastState"},
1321 // Return `AlwaysOff` when power restore policy set to "None"
1322 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1323 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001324
Ed Tanous002d39b2022-05-31 08:59:27 -07001325 auto policyMapsIt = policyMaps.find(policy);
1326 if (policyMapsIt == policyMaps.end())
1327 {
1328 messages::internalError(aResp->res);
1329 return;
1330 }
George Liuc6a620f2020-04-10 17:18:11 +08001331
Ed Tanous002d39b2022-05-31 08:59:27 -07001332 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001333 });
George Liuc6a620f2020-04-10 17:18:11 +08001334}
1335
1336/**
Ali Ahmed19817712021-06-29 17:01:52 -05001337 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1338 * TPM is required for booting the host.
1339 *
1340 * @param[in] aResp Shared pointer for generating response message.
1341 *
1342 * @return None.
1343 */
1344inline void getTrustedModuleRequiredToBoot(
1345 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1346{
1347 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001348 constexpr std::array<std::string_view, 1> interfaces = {
1349 "xyz.openbmc_project.Control.TPM.Policy"};
1350 dbus::utility::getSubTree(
1351 "/", 0, interfaces,
1352 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001353 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001354 if (ec)
1355 {
1356 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1357 << ec;
1358 // This is an optional D-Bus object so just return if
1359 // error occurs
1360 return;
1361 }
1362 if (subtree.empty())
1363 {
1364 // As noted above, this is an optional interface so just return
1365 // if there is no instance found
1366 return;
1367 }
1368
1369 /* When there is more than one TPMEnable object... */
1370 if (subtree.size() > 1)
1371 {
1372 BMCWEB_LOG_DEBUG
1373 << "DBUS response has more than 1 TPM Enable object:"
1374 << subtree.size();
1375 // Throw an internal Error and return
1376 messages::internalError(aResp->res);
1377 return;
1378 }
1379
1380 // Make sure the Dbus response map has a service and objectPath
1381 // field
1382 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1383 {
1384 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1385 messages::internalError(aResp->res);
1386 return;
1387 }
1388
1389 const std::string& path = subtree[0].first;
1390 const std::string& serv = subtree[0].second.begin()->first;
1391
1392 // Valid TPM Enable object found, now reading the current value
1393 sdbusplus::asio::getProperty<bool>(
1394 *crow::connections::systemBus, serv, path,
1395 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001396 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001397 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001398 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001399 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001400 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001401 messages::internalError(aResp->res);
1402 return;
1403 }
1404
Ed Tanous002d39b2022-05-31 08:59:27 -07001405 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001406 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001407 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1408 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001409 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001410 else
1411 {
1412 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1413 "Disabled";
1414 }
1415 });
George Liue99073f2022-12-09 11:06:16 +08001416 });
Ali Ahmed19817712021-06-29 17:01:52 -05001417}
1418
1419/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001420 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1421 * TPM is required for booting the host.
1422 *
1423 * @param[in] aResp Shared pointer for generating response message.
1424 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1425 *
1426 * @return None.
1427 */
1428inline void setTrustedModuleRequiredToBoot(
1429 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1430{
1431 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001432 constexpr std::array<std::string_view, 1> interfaces = {
1433 "xyz.openbmc_project.Control.TPM.Policy"};
1434 dbus::utility::getSubTree(
1435 "/", 0, interfaces,
1436 [aResp,
1437 tpmRequired](const boost::system::error_code& ec,
1438 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001439 if (ec)
1440 {
1441 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1442 << ec;
1443 messages::internalError(aResp->res);
1444 return;
1445 }
1446 if (subtree.empty())
1447 {
1448 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1449 "TrustedModuleRequiredToBoot");
1450 return;
1451 }
1452
1453 /* When there is more than one TPMEnable object... */
1454 if (subtree.size() > 1)
1455 {
1456 BMCWEB_LOG_DEBUG
1457 << "DBUS response has more than 1 TPM Enable object:"
1458 << subtree.size();
1459 // Throw an internal Error and return
1460 messages::internalError(aResp->res);
1461 return;
1462 }
1463
1464 // Make sure the Dbus response map has a service and objectPath
1465 // field
1466 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1467 {
1468 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1469 messages::internalError(aResp->res);
1470 return;
1471 }
1472
1473 const std::string& path = subtree[0].first;
1474 const std::string& serv = subtree[0].second.begin()->first;
1475
1476 if (serv.empty())
1477 {
1478 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1479 messages::internalError(aResp->res);
1480 return;
1481 }
1482
1483 // Valid TPM Enable object found, now setting the value
1484 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001485 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001486 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001487 {
1488 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001489 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001490 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001491 messages::internalError(aResp->res);
1492 return;
1493 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001494 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1495 },
1496 serv, path, "org.freedesktop.DBus.Properties", "Set",
1497 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1498 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001499 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001500}
1501
1502/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301503 * @brief Sets boot properties into DBUS object(s).
1504 *
1505 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001506 * @param[in] bootType The boot type to set.
1507 * @return Integer error code.
1508 */
1509inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001510 const std::optional<std::string>& bootType)
1511{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001512 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001513
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001514 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001515 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001516 return;
1517 }
1518
1519 // Source target specified
1520 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1521 // Figure out which DBUS interface and property to use
1522 if (*bootType == "Legacy")
1523 {
1524 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1525 }
1526 else if (*bootType == "UEFI")
1527 {
1528 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1529 }
1530 else
1531 {
1532 BMCWEB_LOG_DEBUG << "Invalid property value for "
1533 "BootSourceOverrideMode: "
1534 << *bootType;
1535 messages::propertyValueNotInList(aResp->res, *bootType,
1536 "BootSourceOverrideMode");
1537 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001538 }
1539
1540 // Act on validated parameters
1541 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1542
1543 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001544 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001545 if (ec)
1546 {
1547 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1548 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001549 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001550 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001551 return;
1552 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001553 messages::internalError(aResp->res);
1554 return;
1555 }
1556 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001557 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001558 "xyz.openbmc_project.Settings",
1559 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001560 "org.freedesktop.DBus.Properties", "Set",
1561 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001562 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001563}
1564
1565/**
1566 * @brief Sets boot properties into DBUS object(s).
1567 *
1568 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001569 * @param[in] bootType The boot type to set.
1570 * @return Integer error code.
1571 */
1572inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1573 const std::optional<std::string>& bootEnable)
1574{
1575 if (!bootEnable)
1576 {
1577 return;
1578 }
1579 // Source target specified
1580 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1581
1582 bool bootOverrideEnable = false;
1583 bool bootOverridePersistent = false;
1584 // Figure out which DBUS interface and property to use
1585 if (*bootEnable == "Disabled")
1586 {
1587 bootOverrideEnable = false;
1588 }
1589 else if (*bootEnable == "Once")
1590 {
1591 bootOverrideEnable = true;
1592 bootOverridePersistent = false;
1593 }
1594 else if (*bootEnable == "Continuous")
1595 {
1596 bootOverrideEnable = true;
1597 bootOverridePersistent = true;
1598 }
1599 else
1600 {
George Liu0fda0f12021-11-16 10:06:17 +08001601 BMCWEB_LOG_DEBUG
1602 << "Invalid property value for BootSourceOverrideEnabled: "
1603 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001604 messages::propertyValueNotInList(aResp->res, *bootEnable,
1605 "BootSourceOverrideEnabled");
1606 return;
1607 }
1608
1609 // Act on validated parameters
1610 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1611
1612 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001613 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001614 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001615 {
Ed Tanous8a592812022-06-04 09:06:59 -07001616 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001617 messages::internalError(aResp->res);
1618 return;
1619 }
1620 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001621 },
1622 "xyz.openbmc_project.Settings",
1623 "/xyz/openbmc_project/control/host0/boot",
1624 "org.freedesktop.DBus.Properties", "Set",
1625 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001626 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001627
1628 if (!bootOverrideEnable)
1629 {
1630 return;
1631 }
1632
1633 // In case boot override is enabled we need to set correct value for the
1634 // 'one_time' enable DBus interface
1635 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1636 << bootOverridePersistent;
1637
1638 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001639 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001640 if (ec)
1641 {
1642 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1643 messages::internalError(aResp->res);
1644 return;
1645 }
1646 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001647 },
1648 "xyz.openbmc_project.Settings",
1649 "/xyz/openbmc_project/control/host0/boot/one_time",
1650 "org.freedesktop.DBus.Properties", "Set",
1651 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001652 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001653}
1654
1655/**
1656 * @brief Sets boot properties into DBUS object(s).
1657 *
1658 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301659 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301660 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001661 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301662 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001663inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001664 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301665{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001666 std::string bootSourceStr;
1667 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001668
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001669 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301670 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001671 return;
1672 }
1673
1674 // Source target specified
1675 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1676 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001677 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1678 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001679 {
1680 BMCWEB_LOG_DEBUG
1681 << "Invalid property value for BootSourceOverrideTarget: "
1682 << *bootSource;
1683 messages::propertyValueNotInList(aResp->res, *bootSource,
1684 "BootSourceTargetOverride");
1685 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001686 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301687
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001688 // Act on validated parameters
1689 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1690 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001691
1692 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001693 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001694 if (ec)
1695 {
1696 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1697 messages::internalError(aResp->res);
1698 return;
1699 }
1700 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001701 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001702 "xyz.openbmc_project.Settings",
1703 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001704 "org.freedesktop.DBus.Properties", "Set",
1705 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001706 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001707
1708 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001709 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001710 if (ec)
1711 {
1712 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1713 messages::internalError(aResp->res);
1714 return;
1715 }
1716 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001717 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001718 "xyz.openbmc_project.Settings",
1719 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001720 "org.freedesktop.DBus.Properties", "Set",
1721 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001722 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001723}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001724
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001725/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001726 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301727 *
1728 * @param[in] aResp Shared pointer for generating response message.
1729 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001730 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301731 * @param[in] bootEnable The boot override enable from incoming RF request.
1732 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001733 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301734 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001735
1736inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1737 const std::optional<std::string>& bootSource,
1738 const std::optional<std::string>& bootType,
1739 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301740{
1741 BMCWEB_LOG_DEBUG << "Set boot information.";
1742
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001743 setBootModeOrSource(aResp, bootSource);
1744 setBootType(aResp, bootType);
1745 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301746}
1747
George Liuc6a620f2020-04-10 17:18:11 +08001748/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001749 * @brief Sets AssetTag
1750 *
1751 * @param[in] aResp Shared pointer for generating response message.
1752 * @param[in] assetTag "AssetTag" from request.
1753 *
1754 * @return None.
1755 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001756inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001757 const std::string& assetTag)
1758{
George Liue99073f2022-12-09 11:06:16 +08001759 constexpr std::array<std::string_view, 1> interfaces = {
1760 "xyz.openbmc_project.Inventory.Item.System"};
1761 dbus::utility::getSubTree(
1762 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001763 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001764 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001765 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001766 if (ec)
1767 {
1768 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1769 messages::internalError(aResp->res);
1770 return;
1771 }
1772 if (subtree.empty())
1773 {
1774 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1775 messages::internalError(aResp->res);
1776 return;
1777 }
1778 // Assume only 1 system D-Bus object
1779 // Throw an error if there is more than 1
1780 if (subtree.size() > 1)
1781 {
1782 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1783 messages::internalError(aResp->res);
1784 return;
1785 }
1786 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1787 {
1788 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1789 messages::internalError(aResp->res);
1790 return;
1791 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001792
Ed Tanous002d39b2022-05-31 08:59:27 -07001793 const std::string& path = subtree[0].first;
1794 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001795
Ed Tanous002d39b2022-05-31 08:59:27 -07001796 if (service.empty())
1797 {
1798 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1799 messages::internalError(aResp->res);
1800 return;
1801 }
1802
1803 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001804 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001805 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001806 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001807 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1808 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001809 messages::internalError(aResp->res);
1810 return;
1811 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001812 },
1813 service, path, "org.freedesktop.DBus.Properties", "Set",
1814 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1815 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001816 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001817}
1818
1819/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001820 * @brief Sets automaticRetry (Auto Reboot)
1821 *
1822 * @param[in] aResp Shared pointer for generating response message.
1823 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1824 *
1825 * @return None.
1826 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001827inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001828 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001829{
1830 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1831
1832 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001833 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001834
1835 if (automaticRetryConfig == "Disabled")
1836 {
1837 autoRebootEnabled = false;
1838 }
1839 else if (automaticRetryConfig == "RetryAttempts")
1840 {
1841 autoRebootEnabled = true;
1842 }
1843 else
1844 {
George Liu0fda0f12021-11-16 10:06:17 +08001845 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001846 << automaticRetryConfig;
1847 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1848 "AutomaticRetryConfig");
1849 return;
1850 }
1851
1852 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001853 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001854 if (ec)
1855 {
1856 messages::internalError(aResp->res);
1857 return;
1858 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001859 },
1860 "xyz.openbmc_project.Settings",
1861 "/xyz/openbmc_project/control/host0/auto_reboot",
1862 "org.freedesktop.DBus.Properties", "Set",
1863 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001864 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001865}
1866
1867/**
George Liuc6a620f2020-04-10 17:18:11 +08001868 * @brief Sets power restore policy properties.
1869 *
1870 * @param[in] aResp Shared pointer for generating response message.
1871 * @param[in] policy power restore policy properties from request.
1872 *
1873 * @return None.
1874 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001875inline void
1876 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1877 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001878{
1879 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1880
1881 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001882 {"AlwaysOn",
1883 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1884 {"AlwaysOff",
1885 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1886 {"LastState",
1887 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001888
1889 std::string powerRestorPolicy;
1890
Gunnar Mills4e69c902021-01-05 19:50:11 -06001891 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001892 if (policyMapsIt == policyMaps.end())
1893 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001894 messages::propertyValueNotInList(aResp->res, policy,
1895 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001896 return;
1897 }
1898
1899 powerRestorPolicy = policyMapsIt->second;
1900
1901 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001902 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001903 if (ec)
1904 {
1905 messages::internalError(aResp->res);
1906 return;
1907 }
George Liuc6a620f2020-04-10 17:18:11 +08001908 },
1909 "xyz.openbmc_project.Settings",
1910 "/xyz/openbmc_project/control/host0/power_restore_policy",
1911 "org.freedesktop.DBus.Properties", "Set",
1912 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001913 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001914}
1915
AppaRao Pulia6349912019-10-18 17:16:08 +05301916#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1917/**
1918 * @brief Retrieves provisioning status
1919 *
1920 * @param[in] aResp Shared pointer for completing asynchronous calls.
1921 *
1922 * @return None.
1923 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001924inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301925{
1926 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001927 sdbusplus::asio::getAllProperties(
1928 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1929 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001930 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001931 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001932 nlohmann::json& oemPFR =
1933 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1934 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1935 "#OemComputerSystem.OpenBmc";
1936 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001937
Ed Tanous002d39b2022-05-31 08:59:27 -07001938 if (ec)
1939 {
1940 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1941 // not an error, don't have to have the interface
1942 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1943 return;
1944 }
1945
1946 const bool* provState = nullptr;
1947 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001948
1949 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001950 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1951 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001952
1953 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001954 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001955 messages::internalError(aResp->res);
1956 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001957 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301958
Ed Tanous002d39b2022-05-31 08:59:27 -07001959 if ((provState == nullptr) || (lockState == nullptr))
1960 {
1961 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1962 messages::internalError(aResp->res);
1963 return;
1964 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301965
Ed Tanous002d39b2022-05-31 08:59:27 -07001966 if (*provState == true)
1967 {
1968 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301969 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001970 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301971 }
1972 else
1973 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001974 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301975 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001976 }
1977 else
1978 {
1979 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1980 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001981 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301982}
1983#endif
1984
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301985/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001986 * @brief Translate the PowerMode to a response message.
1987 *
1988 * @param[in] aResp Shared pointer for generating response message.
1989 * @param[in] modeValue PowerMode value to be translated
1990 *
1991 * @return None.
1992 */
1993inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1994 const std::string& modeValue)
1995{
George Liu0fda0f12021-11-16 10:06:17 +08001996 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001997 {
1998 aResp->res.jsonValue["PowerMode"] = "Static";
1999 }
George Liu0fda0f12021-11-16 10:06:17 +08002000 else if (
2001 modeValue ==
2002 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002003 {
2004 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2005 }
George Liu0fda0f12021-11-16 10:06:17 +08002006 else if (modeValue ==
2007 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002008 {
2009 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2010 }
George Liu0fda0f12021-11-16 10:06:17 +08002011 else if (modeValue ==
2012 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002013 {
2014 aResp->res.jsonValue["PowerMode"] = "OEM";
2015 }
2016 else
2017 {
2018 // Any other values would be invalid
2019 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2020 messages::internalError(aResp->res);
2021 }
2022}
2023
2024/**
2025 * @brief Retrieves system power mode
2026 *
2027 * @param[in] aResp Shared pointer for generating response message.
2028 *
2029 * @return None.
2030 */
2031inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2032{
2033 BMCWEB_LOG_DEBUG << "Get power mode.";
2034
2035 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002036 constexpr std::array<std::string_view, 1> interfaces = {
2037 "xyz.openbmc_project.Control.Power.Mode"};
2038 dbus::utility::getSubTree(
2039 "/", 0, interfaces,
2040 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002041 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002042 if (ec)
2043 {
2044 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2045 << ec;
2046 // This is an optional D-Bus object so just return if
2047 // error occurs
2048 return;
2049 }
2050 if (subtree.empty())
2051 {
2052 // As noted above, this is an optional interface so just return
2053 // if there is no instance found
2054 return;
2055 }
2056 if (subtree.size() > 1)
2057 {
2058 // More then one PowerMode object is not supported and is an
2059 // error
2060 BMCWEB_LOG_DEBUG
2061 << "Found more than 1 system D-Bus Power.Mode objects: "
2062 << subtree.size();
2063 messages::internalError(aResp->res);
2064 return;
2065 }
2066 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2067 {
2068 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2069 messages::internalError(aResp->res);
2070 return;
2071 }
2072 const std::string& path = subtree[0].first;
2073 const std::string& service = subtree[0].second.begin()->first;
2074 if (service.empty())
2075 {
2076 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2077 messages::internalError(aResp->res);
2078 return;
2079 }
2080 // Valid Power Mode object found, now read the current value
2081 sdbusplus::asio::getProperty<std::string>(
2082 *crow::connections::systemBus, service, path,
2083 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002084 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002085 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002086 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002087 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002088 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002089 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002090 messages::internalError(aResp->res);
2091 return;
2092 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002093
Ed Tanous002d39b2022-05-31 08:59:27 -07002094 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2095 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002096
Ed Tanous002d39b2022-05-31 08:59:27 -07002097 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2098 translatePowerMode(aResp, pmode);
2099 });
George Liue99073f2022-12-09 11:06:16 +08002100 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002101}
2102
2103/**
2104 * @brief Validate the specified mode is valid and return the PowerMode
2105 * name associated with that string
2106 *
2107 * @param[in] aResp Shared pointer for generating response message.
2108 * @param[in] modeString String representing the desired PowerMode
2109 *
2110 * @return PowerMode value or empty string if mode is not valid
2111 */
2112inline std::string
2113 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2114 const std::string& modeString)
2115{
2116 std::string mode;
2117
2118 if (modeString == "Static")
2119 {
2120 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2121 }
2122 else if (modeString == "MaximumPerformance")
2123 {
George Liu0fda0f12021-11-16 10:06:17 +08002124 mode =
2125 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002126 }
2127 else if (modeString == "PowerSaving")
2128 {
2129 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2130 }
2131 else
2132 {
2133 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2134 }
2135 return mode;
2136}
2137
2138/**
2139 * @brief Sets system power mode.
2140 *
2141 * @param[in] aResp Shared pointer for generating response message.
2142 * @param[in] pmode System power mode from request.
2143 *
2144 * @return None.
2145 */
2146inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2147 const std::string& pmode)
2148{
2149 BMCWEB_LOG_DEBUG << "Set power mode.";
2150
2151 std::string powerMode = validatePowerMode(aResp, pmode);
2152 if (powerMode.empty())
2153 {
2154 return;
2155 }
2156
2157 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002158 constexpr std::array<std::string_view, 1> interfaces = {
2159 "xyz.openbmc_project.Control.Power.Mode"};
2160 dbus::utility::getSubTree(
2161 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002162 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002163 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002164 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002165 if (ec)
2166 {
2167 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2168 << ec;
2169 // This is an optional D-Bus object, but user attempted to patch
2170 messages::internalError(aResp->res);
2171 return;
2172 }
2173 if (subtree.empty())
2174 {
2175 // This is an optional D-Bus object, but user attempted to patch
2176 messages::resourceNotFound(aResp->res, "ComputerSystem",
2177 "PowerMode");
2178 return;
2179 }
2180 if (subtree.size() > 1)
2181 {
2182 // More then one PowerMode object is not supported and is an
2183 // error
2184 BMCWEB_LOG_DEBUG
2185 << "Found more than 1 system D-Bus Power.Mode objects: "
2186 << subtree.size();
2187 messages::internalError(aResp->res);
2188 return;
2189 }
2190 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2191 {
2192 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2193 messages::internalError(aResp->res);
2194 return;
2195 }
2196 const std::string& path = subtree[0].first;
2197 const std::string& service = subtree[0].second.begin()->first;
2198 if (service.empty())
2199 {
2200 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2201 messages::internalError(aResp->res);
2202 return;
2203 }
2204
2205 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2206 << path;
2207
2208 // Set the Power Mode property
2209 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002210 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002211 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002212 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002213 messages::internalError(aResp->res);
2214 return;
2215 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002216 },
2217 service, path, "org.freedesktop.DBus.Properties", "Set",
2218 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2219 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002220 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002221}
2222
2223/**
Yong Li51709ff2019-09-30 14:13:04 +08002224 * @brief Translates watchdog timeout action DBUS property value to redfish.
2225 *
2226 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2227 *
2228 * @return Returns as a string, the timeout action in Redfish terms. If
2229 * translation cannot be done, returns an empty string.
2230 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002231inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002232{
2233 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2234 {
2235 return "None";
2236 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002237 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002238 {
2239 return "ResetSystem";
2240 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002241 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002242 {
2243 return "PowerDown";
2244 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002245 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002246 {
2247 return "PowerCycle";
2248 }
2249
2250 return "";
2251}
2252
2253/**
Yong Lic45f0082019-10-10 14:19:01 +08002254 *@brief Translates timeout action from Redfish to DBUS property value.
2255 *
2256 *@param[in] rfAction The timeout action in Redfish.
2257 *
2258 *@return Returns as a string, the time_out action as expected by DBUS.
2259 *If translation cannot be done, returns an empty string.
2260 */
2261
Ed Tanous23a21a12020-07-25 04:45:05 +00002262inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002263{
2264 if (rfAction == "None")
2265 {
2266 return "xyz.openbmc_project.State.Watchdog.Action.None";
2267 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002268 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002269 {
2270 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2271 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002272 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002273 {
2274 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2275 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002276 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002277 {
2278 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2279 }
2280
2281 return "";
2282}
2283
2284/**
Yong Li51709ff2019-09-30 14:13:04 +08002285 * @brief Retrieves host watchdog timer properties over DBUS
2286 *
2287 * @param[in] aResp Shared pointer for completing asynchronous calls.
2288 *
2289 * @return None.
2290 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002291inline void
2292 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002293{
2294 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002295 sdbusplus::asio::getAllProperties(
2296 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2297 "/xyz/openbmc_project/watchdog/host0",
2298 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002299 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002300 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002301 if (ec)
2302 {
2303 // watchdog service is stopped
2304 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2305 return;
2306 }
2307
2308 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2309
2310 nlohmann::json& hostWatchdogTimer =
2311 aResp->res.jsonValue["HostWatchdogTimer"];
2312
2313 // watchdog service is running/enabled
2314 hostWatchdogTimer["Status"]["State"] = "Enabled";
2315
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002316 const bool* enabled = nullptr;
2317 const std::string* expireAction = nullptr;
2318
2319 const bool success = sdbusplus::unpackPropertiesNoThrow(
2320 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2321 "ExpireAction", expireAction);
2322
2323 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002324 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002325 messages::internalError(aResp->res);
2326 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002327 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002328
2329 if (enabled != nullptr)
2330 {
2331 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2332 }
2333
2334 if (expireAction != nullptr)
2335 {
2336 std::string action = dbusToRfWatchdogAction(*expireAction);
2337 if (action.empty())
2338 {
2339 messages::internalError(aResp->res);
2340 return;
2341 }
2342 hostWatchdogTimer["TimeoutAction"] = action;
2343 }
2344 });
Yong Li51709ff2019-09-30 14:13:04 +08002345}
2346
2347/**
Yong Lic45f0082019-10-10 14:19:01 +08002348 * @brief Sets Host WatchDog Timer properties.
2349 *
2350 * @param[in] aResp Shared pointer for generating response message.
2351 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2352 * RF request.
2353 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2354 *
2355 * @return None.
2356 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002357inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002358 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002359 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002360{
2361 BMCWEB_LOG_DEBUG << "Set host watchdog";
2362
2363 if (wdtTimeOutAction)
2364 {
2365 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2366 // check if TimeOut Action is Valid
2367 if (wdtTimeOutActStr.empty())
2368 {
2369 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2370 << *wdtTimeOutAction;
2371 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2372 "TimeoutAction");
2373 return;
2374 }
2375
2376 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002377 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002378 if (ec)
2379 {
2380 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2381 messages::internalError(aResp->res);
2382 return;
2383 }
Yong Lic45f0082019-10-10 14:19:01 +08002384 },
2385 "xyz.openbmc_project.Watchdog",
2386 "/xyz/openbmc_project/watchdog/host0",
2387 "org.freedesktop.DBus.Properties", "Set",
2388 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002389 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002390 }
2391
2392 if (wdtEnable)
2393 {
2394 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002395 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002396 if (ec)
2397 {
2398 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2399 messages::internalError(aResp->res);
2400 return;
2401 }
Yong Lic45f0082019-10-10 14:19:01 +08002402 },
2403 "xyz.openbmc_project.Watchdog",
2404 "/xyz/openbmc_project/watchdog/host0",
2405 "org.freedesktop.DBus.Properties", "Set",
2406 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002407 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002408 }
2409}
2410
Chris Cain37bbf982021-09-20 10:53:09 -05002411/**
2412 * @brief Parse the Idle Power Saver properties into json
2413 *
2414 * @param[in] aResp Shared pointer for completing asynchronous calls.
2415 * @param[in] properties IPS property data from DBus.
2416 *
2417 * @return true if successful
2418 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002419inline bool
2420 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2421 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002422{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002423 const bool* enabled = nullptr;
2424 const uint8_t* enterUtilizationPercent = nullptr;
2425 const uint64_t* enterDwellTime = nullptr;
2426 const uint8_t* exitUtilizationPercent = nullptr;
2427 const uint64_t* exitDwellTime = nullptr;
2428
2429 const bool success = sdbusplus::unpackPropertiesNoThrow(
2430 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002431 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2432 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2433 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002434
2435 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002436 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002437 return false;
2438 }
2439
2440 if (enabled != nullptr)
2441 {
2442 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2443 }
2444
2445 if (enterUtilizationPercent != nullptr)
2446 {
2447 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2448 *enterUtilizationPercent;
2449 }
2450
2451 if (enterDwellTime != nullptr)
2452 {
2453 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2454 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2455 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2456 .count();
2457 }
2458
2459 if (exitUtilizationPercent != nullptr)
2460 {
2461 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2462 *exitUtilizationPercent;
2463 }
2464
2465 if (exitDwellTime != nullptr)
2466 {
2467 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2468 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2469 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2470 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002471 }
2472
2473 return true;
2474}
2475
2476/**
2477 * @brief Retrieves host watchdog timer properties over DBUS
2478 *
2479 * @param[in] aResp Shared pointer for completing asynchronous calls.
2480 *
2481 * @return None.
2482 */
2483inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2484{
2485 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2486
2487 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002488 constexpr std::array<std::string_view, 1> interfaces = {
2489 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2490 dbus::utility::getSubTree(
2491 "/", 0, interfaces,
2492 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002493 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002494 if (ec)
2495 {
2496 BMCWEB_LOG_DEBUG
2497 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2498 << ec;
2499 messages::internalError(aResp->res);
2500 return;
2501 }
2502 if (subtree.empty())
2503 {
2504 // This is an optional interface so just return
2505 // if there is no instance found
2506 BMCWEB_LOG_DEBUG << "No instances found";
2507 return;
2508 }
2509 if (subtree.size() > 1)
2510 {
2511 // More then one PowerIdlePowerSaver object is not supported and
2512 // is an error
2513 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2514 "Power.IdlePowerSaver objects: "
2515 << subtree.size();
2516 messages::internalError(aResp->res);
2517 return;
2518 }
2519 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2520 {
2521 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2522 messages::internalError(aResp->res);
2523 return;
2524 }
2525 const std::string& path = subtree[0].first;
2526 const std::string& service = subtree[0].second.begin()->first;
2527 if (service.empty())
2528 {
2529 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2530 messages::internalError(aResp->res);
2531 return;
2532 }
2533
2534 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002535 sdbusplus::asio::getAllProperties(
2536 *crow::connections::systemBus, service, path,
2537 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002538 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002539 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002540 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002541 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002542 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002543 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002544 messages::internalError(aResp->res);
2545 return;
2546 }
2547
Ed Tanous002d39b2022-05-31 08:59:27 -07002548 if (!parseIpsProperties(aResp, properties))
2549 {
2550 messages::internalError(aResp->res);
2551 return;
2552 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002553 });
George Liue99073f2022-12-09 11:06:16 +08002554 });
Chris Cain37bbf982021-09-20 10:53:09 -05002555
2556 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2557}
2558
2559/**
2560 * @brief Sets Idle Power Saver properties.
2561 *
2562 * @param[in] aResp Shared pointer for generating response message.
2563 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2564 * RF request.
2565 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2566 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2567 * before entering idle state.
2568 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2569 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2570 * before exiting idle state
2571 *
2572 * @return None.
2573 */
2574inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2575 const std::optional<bool> ipsEnable,
2576 const std::optional<uint8_t> ipsEnterUtil,
2577 const std::optional<uint64_t> ipsEnterTime,
2578 const std::optional<uint8_t> ipsExitUtil,
2579 const std::optional<uint64_t> ipsExitTime)
2580{
2581 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2582
2583 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002584 constexpr std::array<std::string_view, 1> interfaces = {
2585 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2586 dbus::utility::getSubTree(
2587 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002588 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002589 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002590 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002591 if (ec)
2592 {
2593 BMCWEB_LOG_DEBUG
2594 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2595 << ec;
2596 messages::internalError(aResp->res);
2597 return;
2598 }
2599 if (subtree.empty())
2600 {
2601 // This is an optional D-Bus object, but user attempted to patch
2602 messages::resourceNotFound(aResp->res, "ComputerSystem",
2603 "IdlePowerSaver");
2604 return;
2605 }
2606 if (subtree.size() > 1)
2607 {
2608 // More then one PowerIdlePowerSaver object is not supported and
2609 // is an error
2610 BMCWEB_LOG_DEBUG
2611 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2612 << subtree.size();
2613 messages::internalError(aResp->res);
2614 return;
2615 }
2616 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2617 {
2618 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2619 messages::internalError(aResp->res);
2620 return;
2621 }
2622 const std::string& path = subtree[0].first;
2623 const std::string& service = subtree[0].second.begin()->first;
2624 if (service.empty())
2625 {
2626 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2627 messages::internalError(aResp->res);
2628 return;
2629 }
Chris Cain37bbf982021-09-20 10:53:09 -05002630
Ed Tanous002d39b2022-05-31 08:59:27 -07002631 // Valid Power IdlePowerSaver object found, now set any values that
2632 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002633
Ed Tanous002d39b2022-05-31 08:59:27 -07002634 if (ipsEnable)
2635 {
2636 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002637 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002638 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002639 {
Ed Tanous8a592812022-06-04 09:06:59 -07002640 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002641 messages::internalError(aResp->res);
2642 return;
2643 }
2644 },
2645 service, path, "org.freedesktop.DBus.Properties", "Set",
2646 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2647 dbus::utility::DbusVariantType(*ipsEnable));
2648 }
2649 if (ipsEnterUtil)
2650 {
2651 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002652 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002653 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002654 {
Ed Tanous8a592812022-06-04 09:06:59 -07002655 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002656 messages::internalError(aResp->res);
2657 return;
2658 }
2659 },
2660 service, path, "org.freedesktop.DBus.Properties", "Set",
2661 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2662 "EnterUtilizationPercent",
2663 dbus::utility::DbusVariantType(*ipsEnterUtil));
2664 }
2665 if (ipsEnterTime)
2666 {
2667 // Convert from seconds into milliseconds for DBus
2668 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2669 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002670 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002671 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002672 {
Ed Tanous8a592812022-06-04 09:06:59 -07002673 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002674 messages::internalError(aResp->res);
2675 return;
2676 }
2677 },
2678 service, path, "org.freedesktop.DBus.Properties", "Set",
2679 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2680 "EnterDwellTime",
2681 dbus::utility::DbusVariantType(timeMilliseconds));
2682 }
2683 if (ipsExitUtil)
2684 {
2685 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002686 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002687 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002688 {
Ed Tanous8a592812022-06-04 09:06:59 -07002689 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002690 messages::internalError(aResp->res);
2691 return;
2692 }
2693 },
2694 service, path, "org.freedesktop.DBus.Properties", "Set",
2695 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2696 "ExitUtilizationPercent",
2697 dbus::utility::DbusVariantType(*ipsExitUtil));
2698 }
2699 if (ipsExitTime)
2700 {
2701 // Convert from seconds into milliseconds for DBus
2702 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2703 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002704 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002705 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002706 {
Ed Tanous8a592812022-06-04 09:06:59 -07002707 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002708 messages::internalError(aResp->res);
2709 return;
2710 }
2711 },
2712 service, path, "org.freedesktop.DBus.Properties", "Set",
2713 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2714 "ExitDwellTime",
2715 dbus::utility::DbusVariantType(timeMilliseconds));
2716 }
George Liue99073f2022-12-09 11:06:16 +08002717 });
Chris Cain37bbf982021-09-20 10:53:09 -05002718
2719 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2720}
2721
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002722inline void handleComputerSystemHead(
2723 crow::App& app, const crow::Request& req,
2724 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2725{
2726 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2727 {
2728 return;
2729 }
2730 asyncResp->res.addHeader(
2731 boost::beast::http::field::link,
2732 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2733}
2734
Yong Lic45f0082019-10-10 14:19:01 +08002735/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002736 * SystemsCollection derived class for delivering ComputerSystems Collection
2737 * Schema
2738 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002739inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002740{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002741 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002742 .privileges(redfish::privileges::headComputerSystemCollection)
2743 .methods(boost::beast::http::verb::head)(
2744 std::bind_front(handleComputerSystemHead, std::ref(app)));
2745
2746 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002747 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002748 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002749 [&app](const crow::Request& req,
2750 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002751 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002752 {
2753 return;
2754 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002755
2756 asyncResp->res.addHeader(
2757 boost::beast::http::field::link,
2758 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002759 asyncResp->res.jsonValue["@odata.type"] =
2760 "#ComputerSystemCollection.ComputerSystemCollection";
2761 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2762 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002763
Ed Tanous002d39b2022-05-31 08:59:27 -07002764 sdbusplus::asio::getProperty<std::string>(
2765 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2766 "/xyz/openbmc_project/network/hypervisor",
2767 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002768 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002769 const std::string& /*hostName*/) {
2770 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2771 ifaceArray = nlohmann::json::array();
2772 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002773
Ed Tanous002d39b2022-05-31 08:59:27 -07002774 nlohmann::json::object_t system;
2775 system["@odata.id"] = "/redfish/v1/Systems/system";
2776 ifaceArray.push_back(std::move(system));
2777 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002778 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002779 {
2780 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2781 nlohmann::json::object_t hypervisor;
2782 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2783 ifaceArray.push_back(std::move(hypervisor));
2784 count = ifaceArray.size();
2785 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002786 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002787 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002788}
Sunitha Harish462023a2020-02-19 08:34:59 -06002789
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002790/**
2791 * Function transceives data with dbus directly.
2792 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002793inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002794{
2795 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2796 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2797 constexpr char const* interfaceName =
2798 "xyz.openbmc_project.Control.Host.NMI";
2799 constexpr char const* method = "NMI";
2800
2801 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002802 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002803 if (ec)
2804 {
2805 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2806 messages::internalError(asyncResp->res);
2807 return;
2808 }
2809 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002810 },
2811 serviceName, objectPath, interfaceName, method);
2812}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002813
2814/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002815 * SystemActionsReset class supports handle POST method for Reset action.
2816 * The class retrieves and sends data directly to D-Bus.
2817 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002818inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002819{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002820 /**
2821 * Function handles POST method request.
2822 * Analyzes POST body message before sends Reset request data to D-Bus.
2823 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002824 BMCWEB_ROUTE(app,
2825 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002826 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002827 .methods(boost::beast::http::verb::post)(
2828 [&app](const crow::Request& req,
2829 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002830 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002831 {
2832 return;
2833 }
2834 std::string resetType;
2835 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2836 resetType))
2837 {
2838 return;
2839 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002840
Ed Tanous002d39b2022-05-31 08:59:27 -07002841 // Get the command and host vs. chassis
2842 std::string command;
2843 bool hostCommand = true;
2844 if ((resetType == "On") || (resetType == "ForceOn"))
2845 {
2846 command = "xyz.openbmc_project.State.Host.Transition.On";
2847 hostCommand = true;
2848 }
2849 else if (resetType == "ForceOff")
2850 {
2851 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2852 hostCommand = false;
2853 }
2854 else if (resetType == "ForceRestart")
2855 {
2856 command =
2857 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2858 hostCommand = true;
2859 }
2860 else if (resetType == "GracefulShutdown")
2861 {
2862 command = "xyz.openbmc_project.State.Host.Transition.Off";
2863 hostCommand = true;
2864 }
2865 else if (resetType == "GracefulRestart")
2866 {
2867 command =
2868 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2869 hostCommand = true;
2870 }
2871 else if (resetType == "PowerCycle")
2872 {
2873 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2874 hostCommand = true;
2875 }
2876 else if (resetType == "Nmi")
2877 {
2878 doNMI(asyncResp);
2879 return;
2880 }
2881 else
2882 {
2883 messages::actionParameterUnknown(asyncResp->res, "Reset",
2884 resetType);
2885 return;
2886 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002887
Ed Tanous002d39b2022-05-31 08:59:27 -07002888 if (hostCommand)
2889 {
2890 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002891 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002892 if (ec)
2893 {
2894 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2895 if (ec.value() == boost::asio::error::invalid_argument)
2896 {
2897 messages::actionParameterNotSupported(
2898 asyncResp->res, resetType, "Reset");
2899 }
2900 else
2901 {
2902 messages::internalError(asyncResp->res);
2903 }
2904 return;
2905 }
2906 messages::success(asyncResp->res);
2907 },
2908 "xyz.openbmc_project.State.Host",
2909 "/xyz/openbmc_project/state/host0",
2910 "org.freedesktop.DBus.Properties", "Set",
2911 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2912 dbus::utility::DbusVariantType{command});
2913 }
2914 else
2915 {
2916 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002917 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002918 if (ec)
2919 {
2920 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2921 if (ec.value() == boost::asio::error::invalid_argument)
2922 {
2923 messages::actionParameterNotSupported(
2924 asyncResp->res, resetType, "Reset");
2925 }
2926 else
2927 {
2928 messages::internalError(asyncResp->res);
2929 }
2930 return;
2931 }
2932 messages::success(asyncResp->res);
2933 },
2934 "xyz.openbmc_project.State.Chassis",
2935 "/xyz/openbmc_project/state/chassis0",
2936 "org.freedesktop.DBus.Properties", "Set",
2937 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2938 dbus::utility::DbusVariantType{command});
2939 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002940 });
2941}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002942
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002943inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002944 App& app, const crow::Request& req,
2945 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2946{
2947 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2948 {
2949 return;
2950 }
2951
2952 asyncResp->res.addHeader(
2953 boost::beast::http::field::link,
2954 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2955}
2956
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002957inline void afterPortRequest(
2958 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2959 const boost::system::error_code& ec,
2960 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2961{
2962 if (ec)
2963 {
2964 messages::internalError(asyncResp->res);
2965 return;
2966 }
2967 for (const auto& data : socketData)
2968 {
2969 const std::string& socketPath = get<0>(data);
2970 const std::string& protocolName = get<1>(data);
2971 bool isProtocolEnabled = get<2>(data);
2972 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2973 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2974 // need to retrieve port number for
2975 // obmc-console-ssh service
2976 if (protocolName == "SSH")
2977 {
2978 getPortNumber(socketPath, [asyncResp, protocolName](
2979 const boost::system::error_code ec1,
2980 int portNumber) {
2981 if (ec1)
2982 {
2983 messages::internalError(asyncResp->res);
2984 return;
2985 }
2986 nlohmann::json& dataJson1 =
2987 asyncResp->res.jsonValue["SerialConsole"];
2988 dataJson1[protocolName]["Port"] = portNumber;
2989 });
2990 }
2991 }
2992}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002993/**
Ed Tanous66173382018-08-15 18:20:59 -07002994 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002995 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002996inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002997{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002998
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002999 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
3000 .privileges(redfish::privileges::headComputerSystem)
3001 .methods(boost::beast::http::verb::head)(
3002 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07003003 /**
3004 * Functions triggers appropriate requests on DBus
3005 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003006 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003007 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003008 .methods(boost::beast::http::verb::get)(
3009 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003010 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3011 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003012 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003013 {
3014 return;
3015 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003016
3017 if (systemName == "hypervisor")
3018 {
3019 handleHypervisorSystemGet(asyncResp);
3020 return;
3021 }
3022
Ed Tanous22d268c2022-05-19 09:39:07 -07003023 if (systemName != "system")
3024 {
3025 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3026 systemName);
3027 return;
3028 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003029 asyncResp->res.addHeader(
3030 boost::beast::http::field::link,
3031 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003032 asyncResp->res.jsonValue["@odata.type"] =
3033 "#ComputerSystem.v1_16_0.ComputerSystem";
3034 asyncResp->res.jsonValue["Name"] = "system";
3035 asyncResp->res.jsonValue["Id"] = "system";
3036 asyncResp->res.jsonValue["SystemType"] = "Physical";
3037 asyncResp->res.jsonValue["Description"] = "Computer System";
3038 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3039 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3040 "Disabled";
3041 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3042 uint64_t(0);
3043 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3044 "Disabled";
3045 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003046
Ed Tanous002d39b2022-05-31 08:59:27 -07003047 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3048 "/redfish/v1/Systems/system/Processors";
3049 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3050 "/redfish/v1/Systems/system/Memory";
3051 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3052 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003053 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3054 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003055
Ed Tanous002d39b2022-05-31 08:59:27 -07003056 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3057 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3058 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3059 ["@Redfish.ActionInfo"] =
3060 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003061
Ed Tanous002d39b2022-05-31 08:59:27 -07003062 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3063 "/redfish/v1/Systems/system/LogServices";
3064 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3065 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003066
Ed Tanous002d39b2022-05-31 08:59:27 -07003067 nlohmann::json::array_t managedBy;
3068 nlohmann::json& manager = managedBy.emplace_back();
3069 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3070 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3071 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3072 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003073
Ed Tanous002d39b2022-05-31 08:59:27 -07003074 // Fill in SerialConsole info
3075 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3076 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3077 true;
Ed Tanous14766872022-03-15 10:44:42 -07003078
Ed Tanous002d39b2022-05-31 08:59:27 -07003079 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3080 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3081 true;
3082 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3083 asyncResp->res
3084 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3085 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003086 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3087 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003088
3089#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003090 // Fill in GraphicalConsole info
3091 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3092 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3093 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003094 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3095 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003096
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003097#endif // BMCWEB_ENABLE_KVM
George Liu7a1dbc42022-12-07 16:03:22 +08003098 constexpr std::array<std::string_view, 4> inventoryForSystems{
Ed Tanous002d39b2022-05-31 08:59:27 -07003099 "xyz.openbmc_project.Inventory.Item.Dimm",
3100 "xyz.openbmc_project.Inventory.Item.Cpu",
3101 "xyz.openbmc_project.Inventory.Item.Drive",
3102 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003103
Ed Tanous002d39b2022-05-31 08:59:27 -07003104 auto health = std::make_shared<HealthPopulate>(asyncResp);
George Liu7a1dbc42022-12-07 16:03:22 +08003105 dbus::utility::getSubTreePaths(
3106 "/", 0, inventoryForSystems,
3107 [health](const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07003108 const std::vector<std::string>& resp) {
3109 if (ec)
3110 {
3111 // no inventory
3112 return;
3113 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003114
Ed Tanous002d39b2022-05-31 08:59:27 -07003115 health->inventory = resp;
George Liu7a1dbc42022-12-07 16:03:22 +08003116 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003117
Ed Tanous002d39b2022-05-31 08:59:27 -07003118 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003119
Ed Tanous002d39b2022-05-31 08:59:27 -07003120 getMainChassisId(asyncResp,
3121 [](const std::string& chassisId,
3122 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3123 nlohmann::json::array_t chassisArray;
3124 nlohmann::json& chassis = chassisArray.emplace_back();
Willy Tueddfc432022-09-26 16:46:38 +00003125 chassis["@odata.id"] = crow::utility::urlFromPieces(
3126 "redfish", "v1", "Chassis", chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003127 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3128 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003129
Ed Tanous002d39b2022-05-31 08:59:27 -07003130 getLocationIndicatorActive(asyncResp);
3131 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3132 getIndicatorLedState(asyncResp);
3133 getComputerSystem(asyncResp, health);
3134 getHostState(asyncResp);
3135 getBootProperties(asyncResp);
3136 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003137 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003138 getPCIeDeviceList(asyncResp, "PCIeDevices");
3139 getHostWatchdogTimer(asyncResp);
3140 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003141 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003142 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003143#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003144 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003145#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003146 getTrustedModuleRequiredToBoot(asyncResp);
3147 getPowerMode(asyncResp);
3148 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003149 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003150
Ed Tanous22d268c2022-05-19 09:39:07 -07003151 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003152 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003153 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003154 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3156 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003157 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003158 {
3159 return;
3160 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003161 if (systemName != "system")
3162 {
3163 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3164 systemName);
3165 return;
3166 }
3167
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003168 asyncResp->res.addHeader(
3169 boost::beast::http::field::link,
3170 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3171
Ed Tanous002d39b2022-05-31 08:59:27 -07003172 std::optional<bool> locationIndicatorActive;
3173 std::optional<std::string> indicatorLed;
3174 std::optional<std::string> assetTag;
3175 std::optional<std::string> powerRestorePolicy;
3176 std::optional<std::string> powerMode;
3177 std::optional<bool> wdtEnable;
3178 std::optional<std::string> wdtTimeOutAction;
3179 std::optional<std::string> bootSource;
3180 std::optional<std::string> bootType;
3181 std::optional<std::string> bootEnable;
3182 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003183 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003184 std::optional<bool> bootTrustedModuleRequired;
3185 std::optional<bool> ipsEnable;
3186 std::optional<uint8_t> ipsEnterUtil;
3187 std::optional<uint64_t> ipsEnterTime;
3188 std::optional<uint8_t> ipsExitUtil;
3189 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003190
Ed Tanous002d39b2022-05-31 08:59:27 -07003191 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003192 if (!json_util::readJsonPatch(
3193 req, asyncResp->res,
3194 "IndicatorLED", indicatorLed,
3195 "LocationIndicatorActive", locationIndicatorActive,
3196 "AssetTag", assetTag,
3197 "PowerRestorePolicy", powerRestorePolicy,
3198 "PowerMode", powerMode,
3199 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3200 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3201 "Boot/BootSourceOverrideTarget", bootSource,
3202 "Boot/BootSourceOverrideMode", bootType,
3203 "Boot/BootSourceOverrideEnabled", bootEnable,
3204 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003205 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003206 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3207 "IdlePowerSaver/Enabled", ipsEnable,
3208 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3209 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3210 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3211 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3212 {
3213 return;
3214 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003215 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003216
Ed Tanous002d39b2022-05-31 08:59:27 -07003217 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003218
Ed Tanous002d39b2022-05-31 08:59:27 -07003219 if (assetTag)
3220 {
3221 setAssetTag(asyncResp, *assetTag);
3222 }
James Feistb49ac872019-05-21 15:12:01 -07003223
Ed Tanous002d39b2022-05-31 08:59:27 -07003224 if (wdtEnable || wdtTimeOutAction)
3225 {
3226 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3227 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003228
Ed Tanous002d39b2022-05-31 08:59:27 -07003229 if (bootSource || bootType || bootEnable)
3230 {
3231 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3232 }
3233 if (bootAutomaticRetry)
3234 {
3235 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3236 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003237
Corey Hardesty797d5da2022-04-26 17:54:52 +08003238 if (bootAutomaticRetryAttempts)
3239 {
3240 setAutomaticRetryAttempts(asyncResp,
3241 bootAutomaticRetryAttempts.value());
3242 }
3243
Ed Tanous002d39b2022-05-31 08:59:27 -07003244 if (bootTrustedModuleRequired)
3245 {
3246 setTrustedModuleRequiredToBoot(asyncResp,
3247 *bootTrustedModuleRequired);
3248 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003249
Ed Tanous002d39b2022-05-31 08:59:27 -07003250 if (locationIndicatorActive)
3251 {
3252 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3253 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003254
Ed Tanous002d39b2022-05-31 08:59:27 -07003255 // TODO (Gunnar): Remove IndicatorLED after enough time has
3256 // passed
3257 if (indicatorLed)
3258 {
3259 setIndicatorLedState(asyncResp, *indicatorLed);
3260 asyncResp->res.addHeader(boost::beast::http::field::warning,
3261 "299 - \"IndicatorLED is deprecated. Use "
3262 "LocationIndicatorActive instead.\"");
3263 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003264
Ed Tanous002d39b2022-05-31 08:59:27 -07003265 if (powerRestorePolicy)
3266 {
3267 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3268 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003269
Ed Tanous002d39b2022-05-31 08:59:27 -07003270 if (powerMode)
3271 {
3272 setPowerMode(asyncResp, *powerMode);
3273 }
Chris Cain37bbf982021-09-20 10:53:09 -05003274
Ed Tanous002d39b2022-05-31 08:59:27 -07003275 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3276 ipsExitTime)
3277 {
3278 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3279 ipsExitUtil, ipsExitTime);
3280 }
3281 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003282}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303283
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003284inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003285 crow::App& app, const crow::Request& req,
3286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3287{
3288 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3289 {
3290 return;
3291 }
3292 asyncResp->res.addHeader(
3293 boost::beast::http::field::link,
3294 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3295}
3296
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303297/**
3298 * SystemResetActionInfo derived class for delivering Computer Systems
3299 * ResetType AllowableValues using ResetInfo schema.
3300 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003301inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303302{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003303 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3304 .privileges(redfish::privileges::headActionInfo)
3305 .methods(boost::beast::http::verb::head)(std::bind_front(
3306 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303307 /**
3308 * Functions triggers appropriate requests on DBus
3309 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003310 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003311 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003312 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003313 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003314 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3315 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003316 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003317 {
3318 return;
3319 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003320
3321 if (systemName == "hypervisor")
3322 {
3323 handleHypervisorResetActionGet(asyncResp);
3324 return;
3325 }
3326
Ed Tanous22d268c2022-05-19 09:39:07 -07003327 if (systemName != "system")
3328 {
3329 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3330 systemName);
3331 return;
3332 }
3333
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003334 asyncResp->res.addHeader(
3335 boost::beast::http::field::link,
3336 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003337
Ed Tanous002d39b2022-05-31 08:59:27 -07003338 asyncResp->res.jsonValue["@odata.id"] =
3339 "/redfish/v1/Systems/system/ResetActionInfo";
3340 asyncResp->res.jsonValue["@odata.type"] =
3341 "#ActionInfo.v1_1_2.ActionInfo";
3342 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3343 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003344
3345 nlohmann::json::array_t parameters;
3346 nlohmann::json::object_t parameter;
3347
3348 parameter["Name"] = "ResetType";
3349 parameter["Required"] = true;
3350 parameter["DataType"] = "String";
3351 nlohmann::json::array_t allowableValues;
3352 allowableValues.emplace_back("On");
3353 allowableValues.emplace_back("ForceOff");
3354 allowableValues.emplace_back("ForceOn");
3355 allowableValues.emplace_back("ForceRestart");
3356 allowableValues.emplace_back("GracefulRestart");
3357 allowableValues.emplace_back("GracefulShutdown");
3358 allowableValues.emplace_back("PowerCycle");
3359 allowableValues.emplace_back("Nmi");
3360 parameter["AllowableValues"] = std::move(allowableValues);
3361 parameters.emplace_back(std::move(parameter));
3362
3363 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003364 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003365}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003366} // namespace redfish