blob: b3094df431ec55c48c4a362e007744680c90b91b [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
James Feistb49ac872019-05-21 15:12:01 -070018#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080020#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080021#include "redfish_util.hpp"
22
John Edward Broadbent7e860f12021-04-08 15:57:16 -070023#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070024#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080025#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070026#include <registries/privilege_registry.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060027#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020028#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050029
Ed Tanousabf2add2019-01-22 16:40:12 -080030#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020031
Ed Tanous1abe55e2018-09-05 08:30:59 -070032namespace redfish
33{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020034
Alpana Kumari9d3ae102019-04-12 06:49:32 -050035/**
36 * @brief Updates the Functional State of DIMMs
37 *
38 * @param[in] aResp Shared pointer for completing asynchronous calls
39 * @param[in] dimmState Dimm's Functional state, true/false
40 *
41 * @return None.
42 */
zhanghch058d1b46d2021-04-01 11:18:24 +080043inline void
44 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanous168e20c2021-12-13 14:39:53 -080045 const dbus::utility::DbusVariantType& dimmState)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050046{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050047 const bool* isDimmFunctional = std::get_if<bool>(&dimmState);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048 if (isDimmFunctional == nullptr)
49 {
50 messages::internalError(aResp->res);
51 return;
52 }
Gunnar Mills698654b2019-10-16 13:17:37 -050053 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050054
Gunnar Mills4e0453b2020-07-08 14:00:30 -050055 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050056 // Update STATE only if previous State was DISABLED and current Dimm is
57 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050058 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
60 if (prevMemSummary == "Disabled")
61 {
62 if (*isDimmFunctional == true)
63 {
64 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
65 "Enabled";
66 }
67 }
68}
69
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050070/*
71 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
72 *
73 * @param[in] aResp Shared pointer for completing asynchronous calls
74 * @param[in] cpuPresenceState CPU present or not
75 *
76 * @return None.
77 */
Ed Tanous168e20c2021-12-13 14:39:53 -080078inline void modifyCpuPresenceState(
79 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
80 const dbus::utility::DbusVariantType& cpuPresenceState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050082 const bool* isCpuPresent = std::get_if<bool>(&cpuPresenceState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050083
84 if (isCpuPresent == nullptr)
85 {
86 messages::internalError(aResp->res);
87 return;
88 }
Gunnar Mills698654b2019-10-16 13:17:37 -050089 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050090
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091 if (*isCpuPresent == true)
92 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050093 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080094 aResp->res.jsonValue["ProcessorSummary"]["Count"];
95 auto procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050096 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080097 if (procCountPtr != nullptr)
98 {
99 // shouldn't be possible to be nullptr
100 *procCountPtr += 1;
101 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500102 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103}
104
105/*
106 * @brief Update "ProcessorSummary" "Status" "State" based on
107 * CPU Functional State
108 *
109 * @param[in] aResp Shared pointer for completing asynchronous calls
110 * @param[in] cpuFunctionalState is CPU functional true/false
111 *
112 * @return None.
113 */
Ed Tanous168e20c2021-12-13 14:39:53 -0800114inline void modifyCpuFunctionalState(
115 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
116 const dbus::utility::DbusVariantType& cpuFunctionalState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500117{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500118 const bool* isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500119
120 if (isCpuFunctional == nullptr)
121 {
122 messages::internalError(aResp->res);
123 return;
124 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500125 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500126
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500127 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500128 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
129
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500130 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500131 // Update STATE only if previous State was Non_Functional and current CPU is
132 // Functional.
133 if (prevProcState == "Disabled")
134 {
135 if (*isCpuFunctional == true)
136 {
137 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
138 "Enabled";
139 }
140 }
141}
142
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143inline void getProcessorProperties(
144 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
145 const std::string& path,
Ed Tanous168e20c2021-12-13 14:39:53 -0800146 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
Ali Ahmed03fbed92021-09-03 02:33:43 -0500147 properties)
148{
149
150 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
151
152 auto getCpuPresenceState =
153 [aResp](const boost::system::error_code ec3,
Ed Tanous168e20c2021-12-13 14:39:53 -0800154 const dbus::utility::DbusVariantType& cpuPresenceCheck) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500155 if (ec3)
156 {
157 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
158 return;
159 }
160 modifyCpuPresenceState(aResp, cpuPresenceCheck);
161 };
162
163 auto getCpuFunctionalState =
164 [aResp](const boost::system::error_code ec3,
Ed Tanous168e20c2021-12-13 14:39:53 -0800165 const dbus::utility::DbusVariantType& cpuFunctionalCheck) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500166 if (ec3)
167 {
168 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
169 return;
170 }
171 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
172 };
173
174 // Get the Presence of CPU
175 crow::connections::systemBus->async_method_call(
176 std::move(getCpuPresenceState), service, path,
177 "org.freedesktop.DBus.Properties", "Get",
178 "xyz.openbmc_project.Inventory.Item", "Present");
179
180 // Get the Functional State
181 crow::connections::systemBus->async_method_call(
182 std::move(getCpuFunctionalState), service, path,
183 "org.freedesktop.DBus.Properties", "Get",
184 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional");
185
186 for (const auto& property : properties)
187 {
188
189 // TODO: Get Model
190
191 // Get CoreCount
192 if (property.first == "CoreCount")
193 {
194
195 // Get CPU CoreCount and add it to the total
196 const uint16_t* coreCountVal =
197 std::get_if<uint16_t>(&property.second);
198
199 if (!coreCountVal)
200 {
201 messages::internalError(aResp->res);
202 return;
203 }
204
205 nlohmann::json& coreCount =
206 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
207 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
208
209 if (coreCountPtr == nullptr)
210 {
211 coreCount = 0;
212 }
213 else
214 {
215 *coreCountPtr += *coreCountVal;
216 }
217 }
218 }
219}
220
221/*
222 * @brief Get ProcessorSummary fields
223 *
224 * @param[in] aResp Shared pointer for completing asynchronous calls
225 * @param[in] service dbus service for Cpu Information
226 * @param[in] path dbus path for Cpu
227 *
228 * @return None.
229 */
230inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
231 const std::string& service,
232 const std::string& path)
233{
234
235 crow::connections::systemBus->async_method_call(
236 [aResp, service,
237 path](const boost::system::error_code ec2,
238 const std::vector<std::pair<
Ed Tanous168e20c2021-12-13 14:39:53 -0800239 std::string, dbus::utility::DbusVariantType>>& properties) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500240 if (ec2)
241 {
242 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
243 messages::internalError(aResp->res);
244 return;
245 }
246 getProcessorProperties(aResp, service, path, properties);
247 },
248 service, path, "org.freedesktop.DBus.Properties", "GetAll",
249 "xyz.openbmc_project.Inventory.Item.Cpu");
250}
251
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500252/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700253 * @brief Retrieves computer system properties over dbus
254 *
255 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500256 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700257 *
258 * @return None.
259 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700260inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800261 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700262 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700263{
Ed Tanous6c34de42018-08-29 13:37:36 -0700264 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500265
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700267 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700268 const boost::system::error_code ec,
269 const std::vector<std::pair<
270 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500271 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
272 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700273 if (ec)
274 {
275 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700276 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700277 return;
278 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700279 // Iterate over all retrieved ObjectPaths.
280 for (const std::pair<std::string,
281 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500282 std::string, std::vector<std::string>>>>&
283 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700284 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500285 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700286 BMCWEB_LOG_DEBUG << "Got path: " << path;
287 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500288 std::pair<std::string, std::vector<std::string>>>&
289 connectionNames = object.second;
Ed Tanous6c34de42018-08-29 13:37:36 -0700290 if (connectionNames.size() < 1)
291 {
292 continue;
293 }
Ed Tanous029573d2019-02-01 10:57:49 -0800294
James Feist5bc2dc82019-10-22 14:33:16 -0700295 auto memoryHealth = std::make_shared<HealthPopulate>(
296 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
297
298 auto cpuHealth = std::make_shared<HealthPopulate>(
299 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
300
301 systemHealth->children.emplace_back(memoryHealth);
302 systemHealth->children.emplace_back(cpuHealth);
303
Ed Tanous029573d2019-02-01 10:57:49 -0800304 // This is not system, so check if it's cpu, dimm, UUID or
305 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500306 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700307 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500308 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700309 {
Ed Tanous029573d2019-02-01 10:57:49 -0800310 if (interfaceName ==
311 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700312 {
Ed Tanous029573d2019-02-01 10:57:49 -0800313 BMCWEB_LOG_DEBUG
314 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500315
Ed Tanous029573d2019-02-01 10:57:49 -0800316 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500317 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700318 path](const boost::system::error_code ec2,
Ed Tanous168e20c2021-12-13 14:39:53 -0800319 const std::vector<std::pair<
320 std::string,
321 dbus::utility::DbusVariantType>>&
Ed Tanousf23b7292020-10-15 09:41:17 -0700322 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000323 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800324 {
325 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000326 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800327 messages::internalError(aResp->res);
328 return;
329 }
330 BMCWEB_LOG_DEBUG << "Got "
331 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500332 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500333
334 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800335 {
Ed Tanous168e20c2021-12-13 14:39:53 -0800336 for (const std::pair<
337 std::string,
338 dbus::utility::
339 DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500340 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700341 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800342 if (property.first !=
343 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700344 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800345 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700346 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500347 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500348 std::get_if<uint32_t>(
349 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800350 if (value == nullptr)
351 {
352 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800353 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800354 continue;
355 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500356 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800357 aResp->res.jsonValue
358 ["MemorySummary"]
359 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500360 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800361 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500362 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800363 if (preValue == nullptr)
364 {
365 continue;
366 }
George Liu0fda0f12021-11-16 10:06:17 +0800367 aResp->res.jsonValue
368 ["MemorySummary"]
369 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800370 *value / (1024 * 1024) +
371 *preValue;
372 aResp->res
373 .jsonValue["MemorySummary"]
374 ["Status"]["State"] =
375 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700376 }
Ed Tanous029573d2019-02-01 10:57:49 -0800377 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500378 else
379 {
380 auto getDimmProperties =
381 [aResp](
382 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000383 ec3,
Ed Tanous168e20c2021-12-13 14:39:53 -0800384 const dbus::utility::
385 DbusVariantType&
386 dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000387 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500388 {
389 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800390 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000391 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500392 return;
393 }
394 updateDimmProperties(aResp,
395 dimmState);
396 };
397 crow::connections::systemBus
398 ->async_method_call(
399 std::move(getDimmProperties),
400 service, path,
George Liu0fda0f12021-11-16 10:06:17 +0800401 "org.freedesktop.DBus.Properties",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500402 "Get",
George Liu0fda0f12021-11-16 10:06:17 +0800403 "xyz.openbmc_project.State.Decorator.OperationalStatus",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500404 "Functional");
405 }
Ed Tanous029573d2019-02-01 10:57:49 -0800406 },
407 connection.first, path,
408 "org.freedesktop.DBus.Properties", "GetAll",
409 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700410
411 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800412 }
413 else if (interfaceName ==
414 "xyz.openbmc_project.Inventory.Item.Cpu")
415 {
416 BMCWEB_LOG_DEBUG
417 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500418
Ali Ahmed03fbed92021-09-03 02:33:43 -0500419 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700420
421 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800422 }
423 else if (interfaceName ==
424 "xyz.openbmc_project.Common.UUID")
425 {
426 BMCWEB_LOG_DEBUG
427 << "Found UUID, now get its properties.";
428 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800429 [aResp](const boost::system::error_code ec3,
430 const std::vector<std::pair<
431 std::string,
432 dbus::utility::DbusVariantType>>&
433 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000434 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800435 {
436 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000437 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800438 messages::internalError(aResp->res);
439 return;
440 }
441 BMCWEB_LOG_DEBUG << "Got "
442 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500443 << " UUID properties.";
Ed Tanous168e20c2021-12-13 14:39:53 -0800444 for (const std::pair<
445 std::string,
446 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500447 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800448 {
Ed Tanous029573d2019-02-01 10:57:49 -0800449 if (property.first == "UUID")
450 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500451 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500452 std::get_if<std::string>(
453 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700454
Ed Tanous029573d2019-02-01 10:57:49 -0800455 if (value != nullptr)
456 {
457 std::string valueStr = *value;
458 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700459 {
Ed Tanous029573d2019-02-01 10:57:49 -0800460 valueStr.insert(8, 1, '-');
461 valueStr.insert(13, 1, '-');
462 valueStr.insert(18, 1, '-');
463 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700464 }
Ed Tanous029573d2019-02-01 10:57:49 -0800465 BMCWEB_LOG_DEBUG << "UUID = "
466 << valueStr;
467 aResp->res.jsonValue["UUID"] =
468 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700469 }
470 }
Ed Tanous029573d2019-02-01 10:57:49 -0800471 }
472 },
473 connection.first, path,
474 "org.freedesktop.DBus.Properties", "GetAll",
475 "xyz.openbmc_project.Common.UUID");
476 }
477 else if (interfaceName ==
478 "xyz.openbmc_project.Inventory.Item.System")
479 {
480 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800481 [aResp](const boost::system::error_code ec2,
482 const std::vector<std::pair<
483 std::string,
484 dbus::utility::DbusVariantType>>&
485 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000486 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800487 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700488 // doesn't have to include this
489 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800490 return;
491 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500492 BMCWEB_LOG_DEBUG
493 << "Got " << propertiesList.size()
494 << " properties for system";
Ed Tanous168e20c2021-12-13 14:39:53 -0800495 for (const std::pair<
496 std::string,
497 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500498 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800499 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500500 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600501 property.first;
502 if ((propertyName == "PartNumber") ||
503 (propertyName == "SerialNumber") ||
504 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500505 (propertyName == "Model") ||
506 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800507 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500508 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600509 std::get_if<std::string>(
510 &property.second);
511 if (value != nullptr)
512 {
513 aResp->res
514 .jsonValue[propertyName] =
515 *value;
516 }
Ed Tanous029573d2019-02-01 10:57:49 -0800517 }
518 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500519
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600520 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500521 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600522 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500523 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800524 },
525 connection.first, path,
526 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800527 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700528
529 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800530 [aResp](const boost::system::error_code ec2,
531 const dbus::utility::DbusVariantType&
532 property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000533 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700534 {
535 // doesn't have to include this
536 // interface
537 return;
538 }
539
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500540 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700541 std::get_if<std::string>(&property);
542 if (value != nullptr)
543 {
544 aResp->res.jsonValue["AssetTag"] =
545 *value;
546 }
547 },
548 connection.first, path,
549 "org.freedesktop.DBus.Properties", "Get",
George Liu0fda0f12021-11-16 10:06:17 +0800550 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
James Feiste4a4b9a2019-06-20 14:08:07 -0700551 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700552 }
553 }
554 }
555 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700556 },
557 "xyz.openbmc_project.ObjectMapper",
558 "/xyz/openbmc_project/object_mapper",
559 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700560 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500561 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700562 "xyz.openbmc_project.Inventory.Decorator.Asset",
563 "xyz.openbmc_project.Inventory.Item.Cpu",
564 "xyz.openbmc_project.Inventory.Item.Dimm",
565 "xyz.openbmc_project.Inventory.Item.System",
566 "xyz.openbmc_project.Common.UUID",
567 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700568}
569
570/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700571 * @brief Retrieves host state properties over dbus
572 *
573 * @param[in] aResp Shared pointer for completing asynchronous calls.
574 *
575 * @return None.
576 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800577inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700578{
579 BMCWEB_LOG_DEBUG << "Get host information.";
580 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800581 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800582 const dbus::utility::DbusVariantType& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700583 if (ec)
584 {
585 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700586 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700587 return;
588 }
Ed Tanous66173382018-08-15 18:20:59 -0700589
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500590 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700591 BMCWEB_LOG_DEBUG << "Host state: " << *s;
592 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700593 {
Ed Tanous66173382018-08-15 18:20:59 -0700594 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800595 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700596 {
Ed Tanous66173382018-08-15 18:20:59 -0700597 aResp->res.jsonValue["PowerState"] = "On";
598 aResp->res.jsonValue["Status"]["State"] = "Enabled";
599 }
George Liu0fda0f12021-11-16 10:06:17 +0800600 else if (*s ==
601 "xyz.openbmc_project.State.Host.HostState.Quiesced")
Gunnar Mills8c888602020-05-01 14:25:09 -0500602 {
603 aResp->res.jsonValue["PowerState"] = "On";
604 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
605 }
George Liu0fda0f12021-11-16 10:06:17 +0800606 else if (
607 *s ==
608 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
Andrew Geissler83935af2020-02-13 10:24:53 -0600609 {
610 aResp->res.jsonValue["PowerState"] = "On";
611 aResp->res.jsonValue["Status"]["State"] = "InTest";
612 }
George Liu0fda0f12021-11-16 10:06:17 +0800613 else if (
614 *s ==
615 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600616 {
617 aResp->res.jsonValue["PowerState"] = "PoweringOn";
Noah Brewer15c27bf2021-04-27 15:24:25 -0500618 aResp->res.jsonValue["Status"]["State"] = "Starting";
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600619 }
George Liu0fda0f12021-11-16 10:06:17 +0800620 else if (
621 *s ==
622 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600623 {
624 aResp->res.jsonValue["PowerState"] = "PoweringOff";
625 aResp->res.jsonValue["Status"]["State"] = "Disabled";
626 }
Ed Tanous66173382018-08-15 18:20:59 -0700627 else
628 {
629 aResp->res.jsonValue["PowerState"] = "Off";
630 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700631 }
632 }
633 },
634 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700635 "org.freedesktop.DBus.Properties", "Get",
636 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700637}
638
639/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500640 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530641 *
642 * @param[in] dbusSource The boot source in DBUS speak.
643 *
644 * @return Returns as a string, the boot source in Redfish terms. If translation
645 * cannot be done, returns an empty string.
646 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000647inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530648{
649 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
650 {
651 return "None";
652 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700653 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530654 {
655 return "Hdd";
656 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700657 if (dbusSource ==
658 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530659 {
660 return "Cd";
661 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700662 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530663 {
664 return "Pxe";
665 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700666 if (dbusSource ==
667 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700668 {
669 return "Usb";
670 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700671 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530672}
673
674/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300675 * @brief Translates boot type DBUS property value to redfish.
676 *
677 * @param[in] dbusType The boot type in DBUS speak.
678 *
679 * @return Returns as a string, the boot type in Redfish terms. If translation
680 * cannot be done, returns an empty string.
681 */
682inline std::string dbusToRfBootType(const std::string& dbusType)
683{
684 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
685 {
686 return "Legacy";
687 }
688 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
689 {
690 return "UEFI";
691 }
692 return "";
693}
694
695/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500696 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530697 *
698 * @param[in] dbusMode The boot mode in DBUS speak.
699 *
700 * @return Returns as a string, the boot mode in Redfish terms. If translation
701 * cannot be done, returns an empty string.
702 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000703inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530704{
705 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
706 {
707 return "None";
708 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700709 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530710 {
711 return "Diags";
712 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700713 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530714 {
715 return "BiosSetup";
716 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700717 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530718}
719
720/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500721 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530722 *
723 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700724 * @param[out] bootSource The DBus source
725 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530726 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700727 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530728 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800729inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500730 const std::string& rfSource,
731 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530732{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300733 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
734 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700735
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530736 if (rfSource == "None")
737 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700738 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530739 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700740 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530741 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700742 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
743 }
744 else if (rfSource == "Hdd")
745 {
746 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
747 }
748 else if (rfSource == "Diags")
749 {
750 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
751 }
752 else if (rfSource == "Cd")
753 {
754 bootSource =
755 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
756 }
757 else if (rfSource == "BiosSetup")
758 {
759 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530760 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700761 else if (rfSource == "Usb")
762 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700763 bootSource =
764 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700765 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530766 else
767 {
George Liu0fda0f12021-11-16 10:06:17 +0800768 BMCWEB_LOG_DEBUG
769 << "Invalid property value for BootSourceOverrideTarget: "
770 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700771 messages::propertyValueNotInList(aResp->res, rfSource,
772 "BootSourceTargetOverride");
773 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700775 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530776}
Ali Ahmed19817712021-06-29 17:01:52 -0500777
Andrew Geissler978b8802020-11-19 13:36:40 -0600778/**
779 * @brief Retrieves boot progress of the system
780 *
781 * @param[in] aResp Shared pointer for generating response message.
782 *
783 * @return None.
784 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800785inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600786{
787 crow::connections::systemBus->async_method_call(
788 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800789 const dbus::utility::DbusVariantType& bootProgress) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600790 if (ec)
791 {
792 // BootProgress is an optional object so just do nothing if
793 // not found
794 return;
795 }
796
797 const std::string* bootProgressStr =
798 std::get_if<std::string>(&bootProgress);
799
800 if (!bootProgressStr)
801 {
802 // Interface implemented but property not found, return error
803 // for that
804 messages::internalError(aResp->res);
805 return;
806 }
807
808 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
809
810 // Now convert the D-Bus BootProgress to the appropriate Redfish
811 // enum
812 std::string rfBpLastState = "None";
George Liu0fda0f12021-11-16 10:06:17 +0800813 if (*bootProgressStr ==
814 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified")
Andrew Geissler978b8802020-11-19 13:36:40 -0600815 {
816 rfBpLastState = "None";
817 }
George Liu0fda0f12021-11-16 10:06:17 +0800818 else if (
819 *bootProgressStr ==
820 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.PrimaryProcInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600821 {
822 rfBpLastState = "PrimaryProcessorInitializationStarted";
823 }
George Liu0fda0f12021-11-16 10:06:17 +0800824 else if (
825 *bootProgressStr ==
826 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.BusInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600827 {
828 rfBpLastState = "BusInitializationStarted";
829 }
George Liu0fda0f12021-11-16 10:06:17 +0800830 else if (
831 *bootProgressStr ==
832 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.MemoryInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600833 {
834 rfBpLastState = "MemoryInitializationStarted";
835 }
George Liu0fda0f12021-11-16 10:06:17 +0800836 else if (
837 *bootProgressStr ==
838 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.SecondaryProcInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600839 {
840 rfBpLastState = "SecondaryProcessorInitializationStarted";
841 }
George Liu0fda0f12021-11-16 10:06:17 +0800842 else if (
843 *bootProgressStr ==
844 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.PCIInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600845 {
846 rfBpLastState = "PCIResourceConfigStarted";
847 }
George Liu0fda0f12021-11-16 10:06:17 +0800848 else if (
849 *bootProgressStr ==
850 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.SystemInitComplete")
Andrew Geissler978b8802020-11-19 13:36:40 -0600851 {
852 rfBpLastState = "SystemHardwareInitializationComplete";
853 }
George Liu0fda0f12021-11-16 10:06:17 +0800854 else if (
855 *bootProgressStr ==
856 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSStart")
Andrew Geissler978b8802020-11-19 13:36:40 -0600857 {
858 rfBpLastState = "OSBootStarted";
859 }
George Liu0fda0f12021-11-16 10:06:17 +0800860 else if (
861 *bootProgressStr ==
862 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSRunning")
Andrew Geissler978b8802020-11-19 13:36:40 -0600863 {
864 rfBpLastState = "OSRunning";
865 }
866 else
867 {
868 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
869 << *bootProgressStr;
870 // Just return the default
871 }
872
873 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
874 },
875 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
876 "org.freedesktop.DBus.Properties", "Get",
877 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
878}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530879
880/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300881 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882 *
883 * @param[in] aResp Shared pointer for generating response message.
884 *
885 * @return None.
886 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300887
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300888inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300889{
890 crow::connections::systemBus->async_method_call(
891 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800892 const dbus::utility::DbusVariantType& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300893 if (ec)
894 {
895 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300896 return;
897 }
898
899 const std::string* bootTypeStr =
900 std::get_if<std::string>(&bootType);
901
902 if (!bootTypeStr)
903 {
904 messages::internalError(aResp->res);
905 return;
906 }
907
908 BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
909
George Liu0fda0f12021-11-16 10:06:17 +0800910 aResp->res
911 .jsonValue["Boot"]
912 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
913 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300914
915 auto rfType = dbusToRfBootType(*bootTypeStr);
916 if (rfType.empty())
917 {
918 messages::internalError(aResp->res);
919 return;
920 }
921
922 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300924 "xyz.openbmc_project.Settings",
925 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300926 "org.freedesktop.DBus.Properties", "Get",
927 "xyz.openbmc_project.Control.Boot.Type", "BootType");
928}
929
930/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300931 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530932 *
933 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530934 *
935 * @return None.
936 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300937
938inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530939{
940 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300941 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800942 const dbus::utility::DbusVariantType& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530943 if (ec)
944 {
945 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
946 messages::internalError(aResp->res);
947 return;
948 }
949
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500950 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530951 std::get_if<std::string>(&bootMode);
952
953 if (!bootModeStr)
954 {
955 messages::internalError(aResp->res);
956 return;
957 }
958
959 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
960
George Liu0fda0f12021-11-16 10:06:17 +0800961 aResp->res
962 .jsonValue["Boot"]
963 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
964 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530965
966 if (*bootModeStr !=
967 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
968 {
969 auto rfMode = dbusToRfBootMode(*bootModeStr);
970 if (!rfMode.empty())
971 {
972 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
973 rfMode;
974 }
975 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530976 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300977 "xyz.openbmc_project.Settings",
978 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530979 "org.freedesktop.DBus.Properties", "Get",
980 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
981}
982
983/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300984 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985 *
986 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530987 *
988 * @return None.
989 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300990
991inline void
992 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530993{
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530994 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300995 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800996 const dbus::utility::DbusVariantType& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530997 if (ec)
998 {
999 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1000 messages::internalError(aResp->res);
1001 return;
1002 }
1003
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001004 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301005 std::get_if<std::string>(&bootSource);
1006
1007 if (!bootSourceStr)
1008 {
1009 messages::internalError(aResp->res);
1010 return;
1011 }
1012 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1013
1014 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1015 if (!rfSource.empty())
1016 {
1017 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1018 rfSource;
1019 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001020
1021 // Get BootMode as BootSourceOverrideTarget is constructed
1022 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001023 getBootOverrideMode(aResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301024 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001025 "xyz.openbmc_project.Settings",
1026 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301027 "org.freedesktop.DBus.Properties", "Get",
1028 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029}
1030
1031/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001032 * @brief This functions abstracts all the logic behind getting a
1033 * "BootSourceOverrideEnabled" property from an overall boot override enable
1034 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301035 *
1036 * @param[in] aResp Shared pointer for generating response message.
1037 *
1038 * @return None.
1039 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301040
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001041inline void
1042 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1043 const bool bootOverrideEnableSetting)
1044{
1045 if (!bootOverrideEnableSetting)
1046 {
1047 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1048 return;
1049 }
1050
1051 // If boot source override is enabled, we need to check 'one_time'
1052 // property to set a correct value for the "BootSourceOverrideEnabled"
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301053 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001054 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08001055 const dbus::utility::DbusVariantType& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301056 if (ec)
1057 {
1058 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001059 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301060 return;
1061 }
1062
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001063 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301064
1065 if (!oneTimePtr)
1066 {
1067 messages::internalError(aResp->res);
1068 return;
1069 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001070
1071 bool oneTimeSetting = *oneTimePtr;
1072
1073 if (oneTimeSetting)
1074 {
1075 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1076 "Once";
1077 }
1078 else
1079 {
1080 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1081 "Continuous";
1082 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301083 },
1084 "xyz.openbmc_project.Settings",
1085 "/xyz/openbmc_project/control/host0/boot/one_time",
1086 "org.freedesktop.DBus.Properties", "Get",
1087 "xyz.openbmc_project.Object.Enable", "Enabled");
1088}
1089
1090/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001091 * @brief Retrieves boot override enable over DBUS
1092 *
1093 * @param[in] aResp Shared pointer for generating response message.
1094 *
1095 * @return None.
1096 */
1097
1098inline void
1099 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1100{
1101 crow::connections::systemBus->async_method_call(
1102 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08001103 const dbus::utility::DbusVariantType& bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001104 if (ec)
1105 {
1106 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1107 messages::internalError(aResp->res);
1108 return;
1109 }
1110
1111 const bool* bootOverrideEnablePtr =
1112 std::get_if<bool>(&bootOverrideEnable);
1113
1114 if (!bootOverrideEnablePtr)
1115 {
1116 messages::internalError(aResp->res);
1117 return;
1118 }
1119
1120 processBootOverrideEnable(aResp, *bootOverrideEnablePtr);
1121 },
1122 "xyz.openbmc_project.Settings",
1123 "/xyz/openbmc_project/control/host0/boot",
1124 "org.freedesktop.DBus.Properties", "Get",
1125 "xyz.openbmc_project.Object.Enable", "Enabled");
1126}
1127
1128/**
1129 * @brief Retrieves boot source override properties
1130 *
1131 * @param[in] aResp Shared pointer for generating response message.
1132 *
1133 * @return None.
1134 */
1135inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1136{
1137 BMCWEB_LOG_DEBUG << "Get boot information.";
1138
1139 getBootOverrideSource(aResp);
1140 getBootOverrideType(aResp);
1141 getBootOverrideEnable(aResp);
1142}
1143
1144/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001145 * @brief Retrieves the Last Reset Time
1146 *
1147 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1148 * and power off. Even though this is the "system" Redfish object look at the
1149 * chassis D-Bus interface for the LastStateChangeTime since this has the
1150 * last power operation time.
1151 *
1152 * @param[in] aResp Shared pointer for generating response message.
1153 *
1154 * @return None.
1155 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001156inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001157{
1158 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1159
1160 crow::connections::systemBus->async_method_call(
1161 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08001162 dbus::utility::DbusVariantType& lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001163 if (ec)
1164 {
1165 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1166 return;
1167 }
1168
1169 const uint64_t* lastResetTimePtr =
1170 std::get_if<uint64_t>(&lastResetTime);
1171
1172 if (!lastResetTimePtr)
1173 {
1174 messages::internalError(aResp->res);
1175 return;
1176 }
1177 // LastStateChangeTime is epoch time, in milliseconds
1178 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Nan Zhou1d8782e2021-11-29 22:23:18 -08001179 uint64_t lastResetTimeStamp = *lastResetTimePtr / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001180
1181 // Convert to ISO 8601 standard
1182 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001183 crow::utility::getDateTimeUint(lastResetTimeStamp);
Gunnar Millsc0557e12020-06-30 11:26:20 -05001184 },
1185 "xyz.openbmc_project.State.Chassis",
1186 "/xyz/openbmc_project/state/chassis0",
1187 "org.freedesktop.DBus.Properties", "Get",
1188 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1189}
1190
1191/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001192 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1193 *
1194 * @param[in] aResp Shared pointer for generating response message.
1195 *
1196 * @return None.
1197 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001198inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001199{
1200 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1201
1202 crow::connections::systemBus->async_method_call(
1203 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08001204 dbus::utility::DbusVariantType& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001205 if (ec)
1206 {
1207 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1208 return;
1209 }
1210
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001211 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001212 std::get_if<bool>(&autoRebootEnabled);
1213
1214 if (!autoRebootEnabledPtr)
1215 {
1216 messages::internalError(aResp->res);
1217 return;
1218 }
1219
1220 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1221 if (*autoRebootEnabledPtr == true)
1222 {
1223 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1224 "RetryAttempts";
1225 // If AutomaticRetry (AutoReboot) is enabled see how many
1226 // attempts are left
1227 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001228 [aResp](const boost::system::error_code ec2,
Ed Tanous168e20c2021-12-13 14:39:53 -08001229 dbus::utility::DbusVariantType&
1230 autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001231 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001232 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001233 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001234 return;
1235 }
1236
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001237 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001238 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1239
1240 if (!autoRebootAttemptsLeftPtr)
1241 {
1242 messages::internalError(aResp->res);
1243 return;
1244 }
1245
1246 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1247 << *autoRebootAttemptsLeftPtr;
1248
1249 aResp->res
1250 .jsonValue["Boot"]
1251 ["RemainingAutomaticRetryAttempts"] =
1252 *autoRebootAttemptsLeftPtr;
1253 },
1254 "xyz.openbmc_project.State.Host",
1255 "/xyz/openbmc_project/state/host0",
1256 "org.freedesktop.DBus.Properties", "Get",
1257 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1258 "AttemptsLeft");
1259 }
1260 else
1261 {
1262 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1263 "Disabled";
1264 }
1265
1266 // Not on D-Bus. Hardcoded here:
1267 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1268 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001269
1270 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1271 // and RetryAttempts. OpenBMC only supports Disabled and
1272 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001273 aResp->res
1274 .jsonValue["Boot"]
1275 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1276 "Disabled", "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001277 },
1278 "xyz.openbmc_project.Settings",
1279 "/xyz/openbmc_project/control/host0/auto_reboot",
1280 "org.freedesktop.DBus.Properties", "Get",
1281 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1282}
1283
1284/**
George Liuc6a620f2020-04-10 17:18:11 +08001285 * @brief Retrieves power restore policy over DBUS.
1286 *
1287 * @param[in] aResp Shared pointer for generating response message.
1288 *
1289 * @return None.
1290 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001291inline void
1292 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001293{
1294 BMCWEB_LOG_DEBUG << "Get power restore policy";
1295
1296 crow::connections::systemBus->async_method_call(
1297 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08001298 dbus::utility::DbusVariantType& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001299 if (ec)
1300 {
1301 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1302 return;
1303 }
1304
George Liu0fda0f12021-11-16 10:06:17 +08001305 const boost::container::flat_map<std::string, std::string> policyMaps = {
1306 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1307 "AlwaysOn"},
1308 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1309 "AlwaysOff"},
1310 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1311 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001312
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001313 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001314
1315 if (!policyPtr)
1316 {
1317 messages::internalError(aResp->res);
1318 return;
1319 }
1320
1321 auto policyMapsIt = policyMaps.find(*policyPtr);
1322 if (policyMapsIt == policyMaps.end())
1323 {
1324 messages::internalError(aResp->res);
1325 return;
1326 }
1327
1328 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1329 },
1330 "xyz.openbmc_project.Settings",
1331 "/xyz/openbmc_project/control/host0/power_restore_policy",
1332 "org.freedesktop.DBus.Properties", "Get",
1333 "xyz.openbmc_project.Control.Power.RestorePolicy",
1334 "PowerRestorePolicy");
1335}
1336
1337/**
Ali Ahmed19817712021-06-29 17:01:52 -05001338 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1339 * TPM is required for booting the host.
1340 *
1341 * @param[in] aResp Shared pointer for generating response message.
1342 *
1343 * @return None.
1344 */
1345inline void getTrustedModuleRequiredToBoot(
1346 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1347{
1348 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1349
1350 crow::connections::systemBus->async_method_call(
1351 [aResp](
1352 const boost::system::error_code ec,
1353 std::vector<std::pair<
1354 std::string,
1355 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1356 subtree) {
1357 if (ec)
1358 {
1359 BMCWEB_LOG_DEBUG
1360 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1361 // This is an optional D-Bus object so just return if
1362 // error occurs
1363 return;
1364 }
1365 if (subtree.size() == 0)
1366 {
1367 // As noted above, this is an optional interface so just return
1368 // if there is no instance found
1369 return;
1370 }
1371
1372 /* When there is more than one TPMEnable object... */
1373 if (subtree.size() > 1)
1374 {
1375 BMCWEB_LOG_DEBUG
1376 << "DBUS response has more than 1 TPM Enable object:"
1377 << subtree.size();
1378 // Throw an internal Error and return
1379 messages::internalError(aResp->res);
1380 return;
1381 }
1382
1383 // Make sure the Dbus response map has a service and objectPath
1384 // field
1385 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1386 {
1387 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1388 messages::internalError(aResp->res);
1389 return;
1390 }
1391
1392 const std::string& path = subtree[0].first;
1393 const std::string& serv = subtree[0].second.begin()->first;
1394
1395 // Valid TPM Enable object found, now reading the current value
1396 crow::connections::systemBus->async_method_call(
1397 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08001398 dbus::utility::DbusVariantType& tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001399 if (ec)
1400 {
1401 BMCWEB_LOG_DEBUG
1402 << "D-BUS response error on TPM.Policy Get" << ec;
1403 messages::internalError(aResp->res);
1404 return;
1405 }
1406
1407 const bool* tpmRequiredVal =
1408 std::get_if<bool>(&tpmRequired);
1409
1410 if (!tpmRequiredVal)
1411 {
1412 messages::internalError(aResp->res);
1413 return;
1414 }
1415
1416 if (*tpmRequiredVal == true)
1417 {
1418 aResp->res
1419 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1420 "Required";
1421 }
1422 else
1423 {
1424 aResp->res
1425 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1426 "Disabled";
1427 }
1428 },
1429 serv, path, "org.freedesktop.DBus.Properties", "Get",
1430 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1431 },
1432 "xyz.openbmc_project.ObjectMapper",
1433 "/xyz/openbmc_project/object_mapper",
1434 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1435 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1436}
1437
1438/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001439 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1440 * TPM is required for booting the host.
1441 *
1442 * @param[in] aResp Shared pointer for generating response message.
1443 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1444 *
1445 * @return None.
1446 */
1447inline void setTrustedModuleRequiredToBoot(
1448 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1449{
1450 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1451
1452 crow::connections::systemBus->async_method_call(
1453 [aResp, tpmRequired](
1454 const boost::system::error_code ec,
1455 std::vector<std::pair<
1456 std::string,
1457 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1458 subtree) {
1459 if (ec)
1460 {
1461 BMCWEB_LOG_DEBUG
1462 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1463 messages::internalError(aResp->res);
1464 return;
1465 }
1466 if (subtree.size() == 0)
1467 {
1468 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1469 "TrustedModuleRequiredToBoot");
1470 return;
1471 }
1472
1473 /* When there is more than one TPMEnable object... */
1474 if (subtree.size() > 1)
1475 {
1476 BMCWEB_LOG_DEBUG
1477 << "DBUS response has more than 1 TPM Enable object:"
1478 << subtree.size();
1479 // Throw an internal Error and return
1480 messages::internalError(aResp->res);
1481 return;
1482 }
1483
1484 // Make sure the Dbus response map has a service and objectPath
1485 // field
1486 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1487 {
1488 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1489 messages::internalError(aResp->res);
1490 return;
1491 }
1492
1493 const std::string& path = subtree[0].first;
1494 const std::string& serv = subtree[0].second.begin()->first;
1495
1496 if (serv.empty())
1497 {
1498 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1499 messages::internalError(aResp->res);
1500 return;
1501 }
1502
1503 // Valid TPM Enable object found, now setting the value
1504 crow::connections::systemBus->async_method_call(
1505 [aResp](const boost::system::error_code ec) {
1506 if (ec)
1507 {
George Liu0fda0f12021-11-16 10:06:17 +08001508 BMCWEB_LOG_DEBUG
1509 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1510 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001511 messages::internalError(aResp->res);
1512 return;
1513 }
1514 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1515 },
1516 serv, path, "org.freedesktop.DBus.Properties", "Set",
1517 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001518 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001519 },
1520 "xyz.openbmc_project.ObjectMapper",
1521 "/xyz/openbmc_project/object_mapper",
1522 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1523 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1524}
1525
1526/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301527 * @brief Sets boot properties into DBUS object(s).
1528 *
1529 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001530 * @param[in] bootType The boot type to set.
1531 * @return Integer error code.
1532 */
1533inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001534 const std::optional<std::string>& bootType)
1535{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001536 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001537
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001538 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001539 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001540 return;
1541 }
1542
1543 // Source target specified
1544 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1545 // Figure out which DBUS interface and property to use
1546 if (*bootType == "Legacy")
1547 {
1548 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1549 }
1550 else if (*bootType == "UEFI")
1551 {
1552 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1553 }
1554 else
1555 {
1556 BMCWEB_LOG_DEBUG << "Invalid property value for "
1557 "BootSourceOverrideMode: "
1558 << *bootType;
1559 messages::propertyValueNotInList(aResp->res, *bootType,
1560 "BootSourceOverrideMode");
1561 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001562 }
1563
1564 // Act on validated parameters
1565 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1566
1567 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001568 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001569 if (ec)
1570 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001571 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1572 if (ec.value() == boost::asio::error::host_unreachable)
1573 {
1574 messages::resourceNotFound(aResp->res, "Set", "BootType");
1575 return;
1576 }
1577 messages::internalError(aResp->res);
1578 return;
1579 }
1580 BMCWEB_LOG_DEBUG << "Boot type update done.";
1581 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001582 "xyz.openbmc_project.Settings",
1583 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001584 "org.freedesktop.DBus.Properties", "Set",
1585 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001586 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001587}
1588
1589/**
1590 * @brief Sets boot properties into DBUS object(s).
1591 *
1592 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001593 * @param[in] bootType The boot type to set.
1594 * @return Integer error code.
1595 */
1596inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1597 const std::optional<std::string>& bootEnable)
1598{
1599 if (!bootEnable)
1600 {
1601 return;
1602 }
1603 // Source target specified
1604 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1605
1606 bool bootOverrideEnable = false;
1607 bool bootOverridePersistent = false;
1608 // Figure out which DBUS interface and property to use
1609 if (*bootEnable == "Disabled")
1610 {
1611 bootOverrideEnable = false;
1612 }
1613 else if (*bootEnable == "Once")
1614 {
1615 bootOverrideEnable = true;
1616 bootOverridePersistent = false;
1617 }
1618 else if (*bootEnable == "Continuous")
1619 {
1620 bootOverrideEnable = true;
1621 bootOverridePersistent = true;
1622 }
1623 else
1624 {
George Liu0fda0f12021-11-16 10:06:17 +08001625 BMCWEB_LOG_DEBUG
1626 << "Invalid property value for BootSourceOverrideEnabled: "
1627 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001628 messages::propertyValueNotInList(aResp->res, *bootEnable,
1629 "BootSourceOverrideEnabled");
1630 return;
1631 }
1632
1633 // Act on validated parameters
1634 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1635
1636 crow::connections::systemBus->async_method_call(
1637 [aResp](const boost::system::error_code ec) {
1638 if (ec)
1639 {
1640 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1641 messages::internalError(aResp->res);
1642 return;
1643 }
1644 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1645 },
1646 "xyz.openbmc_project.Settings",
1647 "/xyz/openbmc_project/control/host0/boot",
1648 "org.freedesktop.DBus.Properties", "Set",
1649 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001650 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001651
1652 if (!bootOverrideEnable)
1653 {
1654 return;
1655 }
1656
1657 // In case boot override is enabled we need to set correct value for the
1658 // 'one_time' enable DBus interface
1659 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1660 << bootOverridePersistent;
1661
1662 crow::connections::systemBus->async_method_call(
1663 [aResp](const boost::system::error_code ec) {
1664 if (ec)
1665 {
1666 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1667 messages::internalError(aResp->res);
1668 return;
1669 }
1670 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1671 },
1672 "xyz.openbmc_project.Settings",
1673 "/xyz/openbmc_project/control/host0/boot/one_time",
1674 "org.freedesktop.DBus.Properties", "Set",
1675 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001676 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001677}
1678
1679/**
1680 * @brief Sets boot properties into DBUS object(s).
1681 *
1682 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301683 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301684 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001685 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301686 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001687inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001688 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301689{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690 std::string bootSourceStr;
1691 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001692
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001693 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301694 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001695 return;
1696 }
1697
1698 // Source target specified
1699 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1700 // Figure out which DBUS interface and property to use
1701 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1702 {
1703 BMCWEB_LOG_DEBUG
1704 << "Invalid property value for BootSourceOverrideTarget: "
1705 << *bootSource;
1706 messages::propertyValueNotInList(aResp->res, *bootSource,
1707 "BootSourceTargetOverride");
1708 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001709 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301710
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001711 // Act on validated parameters
1712 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1713 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001714
1715 crow::connections::systemBus->async_method_call(
1716 [aResp](const boost::system::error_code ec) {
1717 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301718 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001719 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1720 messages::internalError(aResp->res);
1721 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301722 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001723 BMCWEB_LOG_DEBUG << "Boot source update done.";
1724 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001725 "xyz.openbmc_project.Settings",
1726 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001727 "org.freedesktop.DBus.Properties", "Set",
1728 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001729 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001730
1731 crow::connections::systemBus->async_method_call(
1732 [aResp](const boost::system::error_code ec) {
1733 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301734 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001735 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1736 messages::internalError(aResp->res);
1737 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301738 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001739 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1740 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001741 "xyz.openbmc_project.Settings",
1742 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001743 "org.freedesktop.DBus.Properties", "Set",
1744 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001745 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001746}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001747
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001748/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001749 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301750 *
1751 * @param[in] aResp Shared pointer for generating response message.
1752 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001753 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301754 * @param[in] bootEnable The boot override enable from incoming RF request.
1755 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001756 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301757 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001758
1759inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1760 const std::optional<std::string>& bootSource,
1761 const std::optional<std::string>& bootType,
1762 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301763{
1764 BMCWEB_LOG_DEBUG << "Set boot information.";
1765
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001766 setBootModeOrSource(aResp, bootSource);
1767 setBootType(aResp, bootType);
1768 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301769}
1770
George Liuc6a620f2020-04-10 17:18:11 +08001771/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001772 * @brief Sets AssetTag
1773 *
1774 * @param[in] aResp Shared pointer for generating response message.
1775 * @param[in] assetTag "AssetTag" from request.
1776 *
1777 * @return None.
1778 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001779inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001780 const std::string& assetTag)
1781{
1782 crow::connections::systemBus->async_method_call(
1783 [aResp, assetTag](
1784 const boost::system::error_code ec,
1785 const std::vector<std::pair<
1786 std::string,
1787 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1788 subtree) {
1789 if (ec)
1790 {
1791 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1792 messages::internalError(aResp->res);
1793 return;
1794 }
1795 if (subtree.size() == 0)
1796 {
1797 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1798 messages::internalError(aResp->res);
1799 return;
1800 }
1801 // Assume only 1 system D-Bus object
1802 // Throw an error if there is more than 1
1803 if (subtree.size() > 1)
1804 {
1805 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1806 messages::internalError(aResp->res);
1807 return;
1808 }
1809 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1810 {
1811 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1812 messages::internalError(aResp->res);
1813 return;
1814 }
1815
1816 const std::string& path = subtree[0].first;
1817 const std::string& service = subtree[0].second.begin()->first;
1818
1819 if (service.empty())
1820 {
1821 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1822 messages::internalError(aResp->res);
1823 return;
1824 }
1825
1826 crow::connections::systemBus->async_method_call(
1827 [aResp](const boost::system::error_code ec2) {
1828 if (ec2)
1829 {
1830 BMCWEB_LOG_DEBUG
1831 << "D-Bus response error on AssetTag Set " << ec2;
1832 messages::internalError(aResp->res);
1833 return;
1834 }
1835 },
1836 service, path, "org.freedesktop.DBus.Properties", "Set",
1837 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001838 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001839 },
1840 "xyz.openbmc_project.ObjectMapper",
1841 "/xyz/openbmc_project/object_mapper",
1842 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1843 "/xyz/openbmc_project/inventory", int32_t(0),
1844 std::array<const char*, 1>{
1845 "xyz.openbmc_project.Inventory.Item.System"});
1846}
1847
1848/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001849 * @brief Sets automaticRetry (Auto Reboot)
1850 *
1851 * @param[in] aResp Shared pointer for generating response message.
1852 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1853 *
1854 * @return None.
1855 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001856inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001857 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001858{
1859 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1860
1861 // OpenBMC only supports "Disabled" and "RetryAttempts".
1862 bool autoRebootEnabled;
1863
1864 if (automaticRetryConfig == "Disabled")
1865 {
1866 autoRebootEnabled = false;
1867 }
1868 else if (automaticRetryConfig == "RetryAttempts")
1869 {
1870 autoRebootEnabled = true;
1871 }
1872 else
1873 {
George Liu0fda0f12021-11-16 10:06:17 +08001874 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001875 << automaticRetryConfig;
1876 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1877 "AutomaticRetryConfig");
1878 return;
1879 }
1880
1881 crow::connections::systemBus->async_method_call(
1882 [aResp](const boost::system::error_code ec) {
1883 if (ec)
1884 {
1885 messages::internalError(aResp->res);
1886 return;
1887 }
1888 },
1889 "xyz.openbmc_project.Settings",
1890 "/xyz/openbmc_project/control/host0/auto_reboot",
1891 "org.freedesktop.DBus.Properties", "Set",
1892 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001893 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001894}
1895
1896/**
George Liuc6a620f2020-04-10 17:18:11 +08001897 * @brief Sets power restore policy properties.
1898 *
1899 * @param[in] aResp Shared pointer for generating response message.
1900 * @param[in] policy power restore policy properties from request.
1901 *
1902 * @return None.
1903 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001904inline void
1905 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1906 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001907{
1908 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1909
1910 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001911 {"AlwaysOn",
1912 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1913 {"AlwaysOff",
1914 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1915 {"LastState",
1916 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001917
1918 std::string powerRestorPolicy;
1919
Gunnar Mills4e69c902021-01-05 19:50:11 -06001920 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001921 if (policyMapsIt == policyMaps.end())
1922 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001923 messages::propertyValueNotInList(aResp->res, policy,
1924 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001925 return;
1926 }
1927
1928 powerRestorPolicy = policyMapsIt->second;
1929
1930 crow::connections::systemBus->async_method_call(
1931 [aResp](const boost::system::error_code ec) {
1932 if (ec)
1933 {
1934 messages::internalError(aResp->res);
1935 return;
1936 }
1937 },
1938 "xyz.openbmc_project.Settings",
1939 "/xyz/openbmc_project/control/host0/power_restore_policy",
1940 "org.freedesktop.DBus.Properties", "Set",
1941 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001942 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001943}
1944
AppaRao Pulia6349912019-10-18 17:16:08 +05301945#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1946/**
1947 * @brief Retrieves provisioning status
1948 *
1949 * @param[in] aResp Shared pointer for completing asynchronous calls.
1950 *
1951 * @return None.
1952 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001953inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301954{
1955 BMCWEB_LOG_DEBUG << "Get OEM information.";
1956 crow::connections::systemBus->async_method_call(
1957 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001958 const std::vector<std::pair<std::string, VariantType>>&
1959 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301960 nlohmann::json& oemPFR =
1961 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001962 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1963 "#OemComputerSystem.OpenBmc";
1964 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1965
AppaRao Pulia6349912019-10-18 17:16:08 +05301966 if (ec)
1967 {
1968 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301969 // not an error, don't have to have the interface
1970 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301971 return;
1972 }
1973
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001974 const bool* provState = nullptr;
1975 const bool* lockState = nullptr;
1976 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301977 propertiesList)
1978 {
1979 if (property.first == "UfmProvisioned")
1980 {
1981 provState = std::get_if<bool>(&property.second);
1982 }
1983 else if (property.first == "UfmLocked")
1984 {
1985 lockState = std::get_if<bool>(&property.second);
1986 }
1987 }
1988
1989 if ((provState == nullptr) || (lockState == nullptr))
1990 {
1991 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1992 messages::internalError(aResp->res);
1993 return;
1994 }
1995
AppaRao Pulia6349912019-10-18 17:16:08 +05301996 if (*provState == true)
1997 {
1998 if (*lockState == true)
1999 {
2000 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
2001 }
2002 else
2003 {
2004 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
2005 }
2006 }
2007 else
2008 {
2009 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2010 }
2011 },
2012 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2013 "org.freedesktop.DBus.Properties", "GetAll",
2014 "xyz.openbmc_project.PFR.Attributes");
2015}
2016#endif
2017
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302018/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002019 * @brief Translate the PowerMode to a response message.
2020 *
2021 * @param[in] aResp Shared pointer for generating response message.
2022 * @param[in] modeValue PowerMode value to be translated
2023 *
2024 * @return None.
2025 */
2026inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2027 const std::string& modeValue)
2028{
2029 std::string modeString;
2030
George Liu0fda0f12021-11-16 10:06:17 +08002031 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002032 {
2033 aResp->res.jsonValue["PowerMode"] = "Static";
2034 }
George Liu0fda0f12021-11-16 10:06:17 +08002035 else if (
2036 modeValue ==
2037 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002038 {
2039 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2040 }
George Liu0fda0f12021-11-16 10:06:17 +08002041 else if (modeValue ==
2042 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002043 {
2044 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2045 }
George Liu0fda0f12021-11-16 10:06:17 +08002046 else if (modeValue ==
2047 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002048 {
2049 aResp->res.jsonValue["PowerMode"] = "OEM";
2050 }
2051 else
2052 {
2053 // Any other values would be invalid
2054 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2055 messages::internalError(aResp->res);
2056 }
2057}
2058
2059/**
2060 * @brief Retrieves system power mode
2061 *
2062 * @param[in] aResp Shared pointer for generating response message.
2063 *
2064 * @return None.
2065 */
2066inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2067{
2068 BMCWEB_LOG_DEBUG << "Get power mode.";
2069
2070 // Get Power Mode object path:
2071 crow::connections::systemBus->async_method_call(
2072 [aResp](
2073 const boost::system::error_code ec,
2074 const std::vector<std::pair<
2075 std::string,
2076 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2077 subtree) {
2078 if (ec)
2079 {
2080 BMCWEB_LOG_DEBUG
2081 << "DBUS response error on Power.Mode GetSubTree " << ec;
2082 // This is an optional D-Bus object so just return if
2083 // error occurs
2084 return;
2085 }
2086 if (subtree.empty())
2087 {
2088 // As noted above, this is an optional interface so just return
2089 // if there is no instance found
2090 return;
2091 }
2092 if (subtree.size() > 1)
2093 {
2094 // More then one PowerMode object is not supported and is an
2095 // error
2096 BMCWEB_LOG_DEBUG
2097 << "Found more than 1 system D-Bus Power.Mode objects: "
2098 << subtree.size();
2099 messages::internalError(aResp->res);
2100 return;
2101 }
2102 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2103 {
2104 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2105 messages::internalError(aResp->res);
2106 return;
2107 }
2108 const std::string& path = subtree[0].first;
2109 const std::string& service = subtree[0].second.begin()->first;
2110 if (service.empty())
2111 {
2112 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2113 messages::internalError(aResp->res);
2114 return;
2115 }
2116 // Valid Power Mode object found, now read the current value
2117 crow::connections::systemBus->async_method_call(
2118 [aResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -08002119 const dbus::utility::DbusVariantType& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002120 if (ec)
2121 {
2122 BMCWEB_LOG_DEBUG
2123 << "DBUS response error on PowerMode Get: " << ec;
2124 messages::internalError(aResp->res);
2125 return;
2126 }
2127
2128 const std::string* s = std::get_if<std::string>(&pmode);
2129 if (s == nullptr)
2130 {
2131 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2132 messages::internalError(aResp->res);
2133 return;
2134 }
2135
2136 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2137 {"Static", "MaximumPerformance", "PowerSaving"};
2138
2139 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2140 translatePowerMode(aResp, *s);
2141 },
2142 service, path, "org.freedesktop.DBus.Properties", "Get",
2143 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2144 },
2145 "xyz.openbmc_project.ObjectMapper",
2146 "/xyz/openbmc_project/object_mapper",
2147 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2148 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2149}
2150
2151/**
2152 * @brief Validate the specified mode is valid and return the PowerMode
2153 * name associated with that string
2154 *
2155 * @param[in] aResp Shared pointer for generating response message.
2156 * @param[in] modeString String representing the desired PowerMode
2157 *
2158 * @return PowerMode value or empty string if mode is not valid
2159 */
2160inline std::string
2161 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2162 const std::string& modeString)
2163{
2164 std::string mode;
2165
2166 if (modeString == "Static")
2167 {
2168 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2169 }
2170 else if (modeString == "MaximumPerformance")
2171 {
George Liu0fda0f12021-11-16 10:06:17 +08002172 mode =
2173 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002174 }
2175 else if (modeString == "PowerSaving")
2176 {
2177 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2178 }
2179 else
2180 {
2181 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2182 }
2183 return mode;
2184}
2185
2186/**
2187 * @brief Sets system power mode.
2188 *
2189 * @param[in] aResp Shared pointer for generating response message.
2190 * @param[in] pmode System power mode from request.
2191 *
2192 * @return None.
2193 */
2194inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2195 const std::string& pmode)
2196{
2197 BMCWEB_LOG_DEBUG << "Set power mode.";
2198
2199 std::string powerMode = validatePowerMode(aResp, pmode);
2200 if (powerMode.empty())
2201 {
2202 return;
2203 }
2204
2205 // Get Power Mode object path:
2206 crow::connections::systemBus->async_method_call(
2207 [aResp, powerMode](
2208 const boost::system::error_code ec,
2209 const std::vector<std::pair<
2210 std::string,
2211 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2212 subtree) {
2213 if (ec)
2214 {
2215 BMCWEB_LOG_DEBUG
2216 << "DBUS response error on Power.Mode GetSubTree " << ec;
2217 // This is an optional D-Bus object, but user attempted to patch
2218 messages::internalError(aResp->res);
2219 return;
2220 }
2221 if (subtree.empty())
2222 {
2223 // This is an optional D-Bus object, but user attempted to patch
2224 messages::resourceNotFound(aResp->res, "ComputerSystem",
2225 "PowerMode");
2226 return;
2227 }
2228 if (subtree.size() > 1)
2229 {
2230 // More then one PowerMode object is not supported and is an
2231 // error
2232 BMCWEB_LOG_DEBUG
2233 << "Found more than 1 system D-Bus Power.Mode objects: "
2234 << subtree.size();
2235 messages::internalError(aResp->res);
2236 return;
2237 }
2238 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2239 {
2240 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2241 messages::internalError(aResp->res);
2242 return;
2243 }
2244 const std::string& path = subtree[0].first;
2245 const std::string& service = subtree[0].second.begin()->first;
2246 if (service.empty())
2247 {
2248 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2249 messages::internalError(aResp->res);
2250 return;
2251 }
2252
2253 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2254 << path;
2255
2256 // Set the Power Mode property
2257 crow::connections::systemBus->async_method_call(
2258 [aResp](const boost::system::error_code ec) {
2259 if (ec)
2260 {
2261 messages::internalError(aResp->res);
2262 return;
2263 }
2264 },
2265 service, path, "org.freedesktop.DBus.Properties", "Set",
2266 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002267 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002268 },
2269 "xyz.openbmc_project.ObjectMapper",
2270 "/xyz/openbmc_project/object_mapper",
2271 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2272 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2273}
2274
2275/**
Yong Li51709ff2019-09-30 14:13:04 +08002276 * @brief Translates watchdog timeout action DBUS property value to redfish.
2277 *
2278 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2279 *
2280 * @return Returns as a string, the timeout action in Redfish terms. If
2281 * translation cannot be done, returns an empty string.
2282 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002283inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002284{
2285 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2286 {
2287 return "None";
2288 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002289 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002290 {
2291 return "ResetSystem";
2292 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002293 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002294 {
2295 return "PowerDown";
2296 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002297 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002298 {
2299 return "PowerCycle";
2300 }
2301
2302 return "";
2303}
2304
2305/**
Yong Lic45f0082019-10-10 14:19:01 +08002306 *@brief Translates timeout action from Redfish to DBUS property value.
2307 *
2308 *@param[in] rfAction The timeout action in Redfish.
2309 *
2310 *@return Returns as a string, the time_out action as expected by DBUS.
2311 *If translation cannot be done, returns an empty string.
2312 */
2313
Ed Tanous23a21a12020-07-25 04:45:05 +00002314inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002315{
2316 if (rfAction == "None")
2317 {
2318 return "xyz.openbmc_project.State.Watchdog.Action.None";
2319 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002320 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002321 {
2322 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2323 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002324 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002325 {
2326 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2327 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002328 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002329 {
2330 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2331 }
2332
2333 return "";
2334}
2335
2336/**
Yong Li51709ff2019-09-30 14:13:04 +08002337 * @brief Retrieves host watchdog timer properties over DBUS
2338 *
2339 * @param[in] aResp Shared pointer for completing asynchronous calls.
2340 *
2341 * @return None.
2342 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002343inline void
2344 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002345{
2346 BMCWEB_LOG_DEBUG << "Get host watchodg";
2347 crow::connections::systemBus->async_method_call(
2348 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002349 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002350 if (ec)
2351 {
2352 // watchdog service is stopped
2353 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2354 return;
2355 }
2356
2357 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2358
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002359 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002360 aResp->res.jsonValue["HostWatchdogTimer"];
2361
2362 // watchdog service is running/enabled
2363 hostWatchdogTimer["Status"]["State"] = "Enabled";
2364
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002365 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002366 {
2367 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2368 if (property.first == "Enabled")
2369 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002370 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002371
2372 if (!state)
2373 {
2374 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002375 return;
Yong Li51709ff2019-09-30 14:13:04 +08002376 }
2377
2378 hostWatchdogTimer["FunctionEnabled"] = *state;
2379 }
2380 else if (property.first == "ExpireAction")
2381 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002382 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002383 std::get_if<std::string>(&property.second);
2384 if (!s)
2385 {
2386 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002387 return;
Yong Li51709ff2019-09-30 14:13:04 +08002388 }
2389
2390 std::string action = dbusToRfWatchdogAction(*s);
2391 if (action.empty())
2392 {
2393 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002394 return;
Yong Li51709ff2019-09-30 14:13:04 +08002395 }
2396 hostWatchdogTimer["TimeoutAction"] = action;
2397 }
2398 }
2399 },
2400 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2401 "org.freedesktop.DBus.Properties", "GetAll",
2402 "xyz.openbmc_project.State.Watchdog");
2403}
2404
2405/**
Yong Lic45f0082019-10-10 14:19:01 +08002406 * @brief Sets Host WatchDog Timer properties.
2407 *
2408 * @param[in] aResp Shared pointer for generating response message.
2409 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2410 * RF request.
2411 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2412 *
2413 * @return None.
2414 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002415inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002416 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002417 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002418{
2419 BMCWEB_LOG_DEBUG << "Set host watchdog";
2420
2421 if (wdtTimeOutAction)
2422 {
2423 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2424 // check if TimeOut Action is Valid
2425 if (wdtTimeOutActStr.empty())
2426 {
2427 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2428 << *wdtTimeOutAction;
2429 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2430 "TimeoutAction");
2431 return;
2432 }
2433
2434 crow::connections::systemBus->async_method_call(
2435 [aResp](const boost::system::error_code ec) {
2436 if (ec)
2437 {
2438 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2439 messages::internalError(aResp->res);
2440 return;
2441 }
2442 },
2443 "xyz.openbmc_project.Watchdog",
2444 "/xyz/openbmc_project/watchdog/host0",
2445 "org.freedesktop.DBus.Properties", "Set",
2446 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002447 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002448 }
2449
2450 if (wdtEnable)
2451 {
2452 crow::connections::systemBus->async_method_call(
2453 [aResp](const boost::system::error_code ec) {
2454 if (ec)
2455 {
2456 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2457 messages::internalError(aResp->res);
2458 return;
2459 }
2460 },
2461 "xyz.openbmc_project.Watchdog",
2462 "/xyz/openbmc_project/watchdog/host0",
2463 "org.freedesktop.DBus.Properties", "Set",
2464 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002465 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002466 }
2467}
2468
Chris Cain37bbf982021-09-20 10:53:09 -05002469using ipsPropertiesType =
2470 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2471/**
2472 * @brief Parse the Idle Power Saver properties into json
2473 *
2474 * @param[in] aResp Shared pointer for completing asynchronous calls.
2475 * @param[in] properties IPS property data from DBus.
2476 *
2477 * @return true if successful
2478 */
Ed Tanousf6674222021-11-13 09:41:41 -08002479inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2480 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002481{
2482 for (const auto& property : properties)
2483 {
2484 if (property.first == "Enabled")
2485 {
2486 const bool* state = std::get_if<bool>(&property.second);
2487 if (!state)
2488 {
2489 return false;
2490 }
2491 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2492 }
2493 else if (property.first == "EnterUtilizationPercent")
2494 {
2495 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2496 if (!util)
2497 {
2498 return false;
2499 }
2500 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2501 }
2502 else if (property.first == "EnterDwellTime")
2503 {
2504 // Convert Dbus time from milliseconds to seconds
2505 const uint64_t* timeMilliseconds =
2506 std::get_if<uint64_t>(&property.second);
2507 if (!timeMilliseconds)
2508 {
2509 return false;
2510 }
2511 const std::chrono::duration<uint64_t, std::milli> ms(
2512 *timeMilliseconds);
2513 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2514 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2515 .count();
2516 }
2517 else if (property.first == "ExitUtilizationPercent")
2518 {
2519 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2520 if (!util)
2521 {
2522 return false;
2523 }
2524 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2525 }
2526 else if (property.first == "ExitDwellTime")
2527 {
2528 // Convert Dbus time from milliseconds to seconds
2529 const uint64_t* timeMilliseconds =
2530 std::get_if<uint64_t>(&property.second);
2531 if (!timeMilliseconds)
2532 {
2533 return false;
2534 }
2535 const std::chrono::duration<uint64_t, std::milli> ms(
2536 *timeMilliseconds);
2537 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2538 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2539 .count();
2540 }
2541 else
2542 {
2543 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2544 << property.first;
2545 }
2546 }
2547
2548 return true;
2549}
2550
2551/**
2552 * @brief Retrieves host watchdog timer properties over DBUS
2553 *
2554 * @param[in] aResp Shared pointer for completing asynchronous calls.
2555 *
2556 * @return None.
2557 */
2558inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2559{
2560 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2561
2562 // Get IdlePowerSaver object path:
2563 crow::connections::systemBus->async_method_call(
2564 [aResp](
2565 const boost::system::error_code ec,
2566 const std::vector<std::pair<
2567 std::string,
2568 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2569 subtree) {
2570 if (ec)
2571 {
2572 BMCWEB_LOG_DEBUG
2573 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2574 << ec;
2575 messages::internalError(aResp->res);
2576 return;
2577 }
2578 if (subtree.empty())
2579 {
2580 // This is an optional interface so just return
2581 // if there is no instance found
2582 BMCWEB_LOG_DEBUG << "No instances found";
2583 return;
2584 }
2585 if (subtree.size() > 1)
2586 {
2587 // More then one PowerIdlePowerSaver object is not supported and
2588 // is an error
2589 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2590 "Power.IdlePowerSaver objects: "
2591 << subtree.size();
2592 messages::internalError(aResp->res);
2593 return;
2594 }
2595 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2596 {
2597 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2598 messages::internalError(aResp->res);
2599 return;
2600 }
2601 const std::string& path = subtree[0].first;
2602 const std::string& service = subtree[0].second.begin()->first;
2603 if (service.empty())
2604 {
2605 BMCWEB_LOG_DEBUG
2606 << "Power.IdlePowerSaver service mapper error!";
2607 messages::internalError(aResp->res);
2608 return;
2609 }
2610
2611 // Valid IdlePowerSaver object found, now read the current values
2612 crow::connections::systemBus->async_method_call(
2613 [aResp](const boost::system::error_code ec,
2614 ipsPropertiesType& properties) {
2615 if (ec)
2616 {
2617 BMCWEB_LOG_ERROR
2618 << "DBUS response error on IdlePowerSaver GetAll: "
2619 << ec;
2620 messages::internalError(aResp->res);
2621 return;
2622 }
2623
2624 if (parseIpsProperties(aResp, properties) == false)
2625 {
2626 messages::internalError(aResp->res);
2627 return;
2628 }
2629 },
2630 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2631 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2632 },
2633 "xyz.openbmc_project.ObjectMapper",
2634 "/xyz/openbmc_project/object_mapper",
2635 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2636 std::array<const char*, 1>{
2637 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2638
2639 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2640}
2641
2642/**
2643 * @brief Sets Idle Power Saver properties.
2644 *
2645 * @param[in] aResp Shared pointer for generating response message.
2646 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2647 * RF request.
2648 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2649 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2650 * before entering idle state.
2651 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2652 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2653 * before exiting idle state
2654 *
2655 * @return None.
2656 */
2657inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2658 const std::optional<bool> ipsEnable,
2659 const std::optional<uint8_t> ipsEnterUtil,
2660 const std::optional<uint64_t> ipsEnterTime,
2661 const std::optional<uint8_t> ipsExitUtil,
2662 const std::optional<uint64_t> ipsExitTime)
2663{
2664 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2665
2666 // Get IdlePowerSaver object path:
2667 crow::connections::systemBus->async_method_call(
2668 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2669 ipsExitTime](
2670 const boost::system::error_code ec,
2671 const std::vector<std::pair<
2672 std::string,
2673 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2674 subtree) {
2675 if (ec)
2676 {
2677 BMCWEB_LOG_DEBUG
2678 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2679 << ec;
2680 messages::internalError(aResp->res);
2681 return;
2682 }
2683 if (subtree.empty())
2684 {
2685 // This is an optional D-Bus object, but user attempted to patch
2686 messages::resourceNotFound(aResp->res, "ComputerSystem",
2687 "IdlePowerSaver");
2688 return;
2689 }
2690 if (subtree.size() > 1)
2691 {
2692 // More then one PowerIdlePowerSaver object is not supported and
2693 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002694 BMCWEB_LOG_DEBUG
2695 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2696 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002697 messages::internalError(aResp->res);
2698 return;
2699 }
2700 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2701 {
2702 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2703 messages::internalError(aResp->res);
2704 return;
2705 }
2706 const std::string& path = subtree[0].first;
2707 const std::string& service = subtree[0].second.begin()->first;
2708 if (service.empty())
2709 {
2710 BMCWEB_LOG_DEBUG
2711 << "Power.IdlePowerSaver service mapper error!";
2712 messages::internalError(aResp->res);
2713 return;
2714 }
2715
2716 // Valid Power IdlePowerSaver object found, now set any values that
2717 // need to be updated
2718
2719 if (ipsEnable)
2720 {
2721 crow::connections::systemBus->async_method_call(
2722 [aResp](const boost::system::error_code ec) {
2723 if (ec)
2724 {
2725 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2726 messages::internalError(aResp->res);
2727 return;
2728 }
2729 },
2730 service, path, "org.freedesktop.DBus.Properties", "Set",
2731 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002732 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002733 }
2734 if (ipsEnterUtil)
2735 {
2736 crow::connections::systemBus->async_method_call(
2737 [aResp](const boost::system::error_code ec) {
2738 if (ec)
2739 {
2740 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2741 messages::internalError(aResp->res);
2742 return;
2743 }
2744 },
2745 service, path, "org.freedesktop.DBus.Properties", "Set",
2746 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2747 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002748 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002749 }
2750 if (ipsEnterTime)
2751 {
2752 // Convert from seconds into milliseconds for DBus
2753 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2754 crow::connections::systemBus->async_method_call(
2755 [aResp](const boost::system::error_code ec) {
2756 if (ec)
2757 {
2758 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2759 messages::internalError(aResp->res);
2760 return;
2761 }
2762 },
2763 service, path, "org.freedesktop.DBus.Properties", "Set",
2764 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002765 "EnterDwellTime",
2766 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002767 }
2768 if (ipsExitUtil)
2769 {
2770 crow::connections::systemBus->async_method_call(
2771 [aResp](const boost::system::error_code ec) {
2772 if (ec)
2773 {
2774 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2775 messages::internalError(aResp->res);
2776 return;
2777 }
2778 },
2779 service, path, "org.freedesktop.DBus.Properties", "Set",
2780 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2781 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002782 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002783 }
2784 if (ipsExitTime)
2785 {
2786 // Convert from seconds into milliseconds for DBus
2787 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2788 crow::connections::systemBus->async_method_call(
2789 [aResp](const boost::system::error_code ec) {
2790 if (ec)
2791 {
2792 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2793 messages::internalError(aResp->res);
2794 return;
2795 }
2796 },
2797 service, path, "org.freedesktop.DBus.Properties", "Set",
2798 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002799 "ExitDwellTime",
2800 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002801 }
2802 },
2803 "xyz.openbmc_project.ObjectMapper",
2804 "/xyz/openbmc_project/object_mapper",
2805 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2806 std::array<const char*, 1>{
2807 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2808
2809 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2810}
2811
Yong Lic45f0082019-10-10 14:19:01 +08002812/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002813 * SystemsCollection derived class for delivering ComputerSystems Collection
2814 * Schema
2815 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002816inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002817{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002818 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002819 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002820 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002821 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002822 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2823 asyncResp->res.jsonValue["@odata.type"] =
2824 "#ComputerSystemCollection.ComputerSystemCollection";
2825 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2826 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002827
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002828 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -08002829 [asyncResp](
2830 const boost::system::error_code ec,
2831 const dbus::utility::DbusVariantType& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002832 nlohmann::json& ifaceArray =
2833 asyncResp->res.jsonValue["Members"];
2834 ifaceArray = nlohmann::json::array();
2835 auto& count =
2836 asyncResp->res.jsonValue["Members@odata.count"];
2837 ifaceArray.push_back(
2838 {{"@odata.id", "/redfish/v1/Systems/system"}});
2839 count = ifaceArray.size();
2840 if (!ec)
2841 {
2842 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2843 ifaceArray.push_back(
2844 {{"@odata.id",
2845 "/redfish/v1/Systems/hypervisor"}});
2846 count = ifaceArray.size();
2847 }
2848 },
2849 "xyz.openbmc_project.Settings",
2850 "/xyz/openbmc_project/network/hypervisor",
2851 "org.freedesktop.DBus.Properties", "Get",
2852 "xyz.openbmc_project.Network.SystemConfiguration",
2853 "HostName");
2854 });
2855}
Sunitha Harish462023a2020-02-19 08:34:59 -06002856
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002857/**
2858 * Function transceives data with dbus directly.
2859 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002860inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002861{
2862 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2863 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2864 constexpr char const* interfaceName =
2865 "xyz.openbmc_project.Control.Host.NMI";
2866 constexpr char const* method = "NMI";
2867
2868 crow::connections::systemBus->async_method_call(
2869 [asyncResp](const boost::system::error_code ec) {
2870 if (ec)
2871 {
2872 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2873 messages::internalError(asyncResp->res);
2874 return;
2875 }
2876 messages::success(asyncResp->res);
2877 },
2878 serviceName, objectPath, interfaceName, method);
2879}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002880
2881/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002882 * SystemActionsReset class supports handle POST method for Reset action.
2883 * The class retrieves and sends data directly to D-Bus.
2884 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002885inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002886{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002887 /**
2888 * Function handles POST method request.
2889 * Analyzes POST body message before sends Reset request data to D-Bus.
2890 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002891 BMCWEB_ROUTE(app,
2892 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002893 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002894 .methods(
2895 boost::beast::http::verb::
2896 post)([](const crow::Request& req,
2897 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2898 std::string resetType;
2899 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2900 resetType))
2901 {
2902 return;
2903 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002904
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002905 // Get the command and host vs. chassis
2906 std::string command;
2907 bool hostCommand;
2908 if ((resetType == "On") || (resetType == "ForceOn"))
2909 {
2910 command = "xyz.openbmc_project.State.Host.Transition.On";
2911 hostCommand = true;
2912 }
2913 else if (resetType == "ForceOff")
2914 {
2915 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2916 hostCommand = false;
2917 }
2918 else if (resetType == "ForceRestart")
2919 {
2920 command =
2921 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2922 hostCommand = true;
2923 }
2924 else if (resetType == "GracefulShutdown")
2925 {
2926 command = "xyz.openbmc_project.State.Host.Transition.Off";
2927 hostCommand = true;
2928 }
2929 else if (resetType == "GracefulRestart")
2930 {
George Liu0fda0f12021-11-16 10:06:17 +08002931 command =
2932 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002933 hostCommand = true;
2934 }
2935 else if (resetType == "PowerCycle")
2936 {
2937 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2938 hostCommand = true;
2939 }
2940 else if (resetType == "Nmi")
2941 {
2942 doNMI(asyncResp);
2943 return;
2944 }
2945 else
2946 {
2947 messages::actionParameterUnknown(asyncResp->res, "Reset",
2948 resetType);
2949 return;
2950 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002951
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002952 if (hostCommand)
2953 {
2954 crow::connections::systemBus->async_method_call(
2955 [asyncResp, resetType](const boost::system::error_code ec) {
2956 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002957 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002958 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2959 if (ec.value() ==
2960 boost::asio::error::invalid_argument)
2961 {
2962 messages::actionParameterNotSupported(
2963 asyncResp->res, resetType, "Reset");
2964 }
2965 else
2966 {
2967 messages::internalError(asyncResp->res);
2968 }
2969 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002970 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002971 messages::success(asyncResp->res);
2972 },
2973 "xyz.openbmc_project.State.Host",
2974 "/xyz/openbmc_project/state/host0",
2975 "org.freedesktop.DBus.Properties", "Set",
2976 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002977 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002978 }
2979 else
2980 {
2981 crow::connections::systemBus->async_method_call(
2982 [asyncResp, resetType](const boost::system::error_code ec) {
2983 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002984 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002985 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2986 if (ec.value() ==
2987 boost::asio::error::invalid_argument)
2988 {
2989 messages::actionParameterNotSupported(
2990 asyncResp->res, resetType, "Reset");
2991 }
2992 else
2993 {
2994 messages::internalError(asyncResp->res);
2995 }
2996 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002997 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002998 messages::success(asyncResp->res);
2999 },
3000 "xyz.openbmc_project.State.Chassis",
3001 "/xyz/openbmc_project/state/chassis0",
3002 "org.freedesktop.DBus.Properties", "Set",
3003 "xyz.openbmc_project.State.Chassis",
3004 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08003005 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003006 }
3007 });
3008}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003009
3010/**
Ed Tanous66173382018-08-15 18:20:59 -07003011 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003012 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003013inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003014{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003015
Ed Tanous1abe55e2018-09-05 08:30:59 -07003016 /**
3017 * Functions triggers appropriate requests on DBus
3018 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003019 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003020 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003021 .methods(
3022 boost::beast::http::verb::
3023 get)([](const crow::Request&,
3024 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3025 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05003026 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003027 asyncResp->res.jsonValue["Name"] = "system";
3028 asyncResp->res.jsonValue["Id"] = "system";
3029 asyncResp->res.jsonValue["SystemType"] = "Physical";
3030 asyncResp->res.jsonValue["Description"] = "Computer System";
3031 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3032 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3033 "Disabled";
3034 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3035 uint64_t(0);
3036 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3037 "Disabled";
3038 asyncResp->res.jsonValue["@odata.id"] =
3039 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003040
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003041 asyncResp->res.jsonValue["Processors"] = {
3042 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
3043 asyncResp->res.jsonValue["Memory"] = {
3044 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
3045 asyncResp->res.jsonValue["Storage"] = {
3046 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08003047
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003048 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
3049 {"target",
3050 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
3051 {"@Redfish.ActionInfo",
3052 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003053
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003054 asyncResp->res.jsonValue["LogServices"] = {
3055 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003056
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003057 asyncResp->res.jsonValue["Bios"] = {
3058 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08003059
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003060 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
3061 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08003062
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003063 asyncResp->res.jsonValue["Status"] = {
3064 {"Health", "OK"},
3065 {"State", "Enabled"},
3066 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003067
3068 // Fill in SerialConsole info
3069 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
3070 15;
3071 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
3072 {"ServiceEnabled", true},
3073 };
3074 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3075 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
3076 {"ServiceEnabled", true},
3077 {"Port", 2200},
3078 // https://github.com/openbmc/docs/blob/master/console.md
3079 {"HotKeySequenceDisplay", "Press ~. to exit console"},
3080 };
3081
3082#ifdef BMCWEB_ENABLE_KVM
3083 // Fill in GraphicalConsole info
3084 asyncResp->res.jsonValue["GraphicalConsole"] = {
3085 {"ServiceEnabled", true},
3086 {"MaxConcurrentSessions", 4},
3087 {"ConnectTypesSupported", {"KVMIP"}},
3088 };
3089#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003090 constexpr const std::array<const char*, 4> inventoryForSystems = {
3091 "xyz.openbmc_project.Inventory.Item.Dimm",
3092 "xyz.openbmc_project.Inventory.Item.Cpu",
3093 "xyz.openbmc_project.Inventory.Item.Drive",
3094 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003095
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003096 auto health = std::make_shared<HealthPopulate>(asyncResp);
3097 crow::connections::systemBus->async_method_call(
3098 [health](const boost::system::error_code ec,
3099 std::vector<std::string>& resp) {
3100 if (ec)
3101 {
3102 // no inventory
3103 return;
3104 }
3105
3106 health->inventory = std::move(resp);
3107 },
3108 "xyz.openbmc_project.ObjectMapper",
3109 "/xyz/openbmc_project/object_mapper",
3110 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
3111 int32_t(0), inventoryForSystems);
3112
3113 health->populate();
3114
3115 getMainChassisId(
3116 asyncResp, [](const std::string& chassisId,
3117 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3118 aRsp->res.jsonValue["Links"]["Chassis"] = {
3119 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
3120 });
3121
3122 getLocationIndicatorActive(asyncResp);
3123 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3124 getIndicatorLedState(asyncResp);
3125 getComputerSystem(asyncResp, health);
3126 getHostState(asyncResp);
3127 getBootProperties(asyncResp);
3128 getBootProgress(asyncResp);
3129 getPCIeDeviceList(asyncResp, "PCIeDevices");
3130 getHostWatchdogTimer(asyncResp);
3131 getPowerRestorePolicy(asyncResp);
3132 getAutomaticRetry(asyncResp);
3133 getLastResetTime(asyncResp);
3134#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
3135 getProvisioningStatus(asyncResp);
3136#endif
Ali Ahmed19817712021-06-29 17:01:52 -05003137 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05003138 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003139 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003140 });
3141 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003142 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003143 .methods(boost::beast::http::verb::patch)(
3144 [](const crow::Request& req,
3145 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3146 std::optional<bool> locationIndicatorActive;
3147 std::optional<std::string> indicatorLed;
3148 std::optional<nlohmann::json> bootProps;
3149 std::optional<nlohmann::json> wdtTimerProps;
3150 std::optional<std::string> assetTag;
3151 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003152 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003153 std::optional<nlohmann::json> ipsProps;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003154 if (!json_util::readJson(
3155 req, asyncResp->res, "IndicatorLED", indicatorLed,
3156 "LocationIndicatorActive", locationIndicatorActive,
3157 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3158 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003159 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3160 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003161 {
James Feistb49ac872019-05-21 15:12:01 -07003162 return;
3163 }
3164
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003165 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003166
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003167 if (assetTag)
3168 {
3169 setAssetTag(asyncResp, *assetTag);
3170 }
James Feistb49ac872019-05-21 15:12:01 -07003171
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003172 if (wdtTimerProps)
3173 {
3174 std::optional<bool> wdtEnable;
3175 std::optional<std::string> wdtTimeOutAction;
3176
3177 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3178 "FunctionEnabled", wdtEnable,
3179 "TimeoutAction", wdtTimeOutAction))
3180 {
3181 return;
3182 }
3183 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3184 }
3185
3186 if (bootProps)
3187 {
3188 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003189 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003190 std::optional<std::string> bootEnable;
3191 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003192 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003193
3194 if (!json_util::readJson(
3195 *bootProps, asyncResp->res,
3196 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003197 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003198 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003199 "AutomaticRetryConfig", automaticRetryConfig,
3200 "TrustedModuleRequiredToBoot",
3201 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003202 {
3203 return;
3204 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003205
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003206 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003207 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003208 setBootProperties(asyncResp, bootSource, bootType,
3209 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003210 }
3211 if (automaticRetryConfig)
3212 {
3213 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3214 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003215
3216 if (trustedModuleRequiredToBoot)
3217 {
3218 setTrustedModuleRequiredToBoot(
3219 asyncResp, *trustedModuleRequiredToBoot);
3220 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003221 }
3222
3223 if (locationIndicatorActive)
3224 {
3225 setLocationIndicatorActive(asyncResp,
3226 *locationIndicatorActive);
3227 }
3228
3229 // TODO (Gunnar): Remove IndicatorLED after enough time has
3230 // passed
3231 if (indicatorLed)
3232 {
3233 setIndicatorLedState(asyncResp, *indicatorLed);
3234 asyncResp->res.addHeader(
3235 boost::beast::http::field::warning,
3236 "299 - \"IndicatorLED is deprecated. Use "
3237 "LocationIndicatorActive instead.\"");
3238 }
3239
3240 if (powerRestorePolicy)
3241 {
3242 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3243 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003244
3245 if (powerMode)
3246 {
3247 setPowerMode(asyncResp, *powerMode);
3248 }
Chris Cain37bbf982021-09-20 10:53:09 -05003249
3250 if (ipsProps)
3251 {
3252 std::optional<bool> ipsEnable;
3253 std::optional<uint8_t> ipsEnterUtil;
3254 std::optional<uint64_t> ipsEnterTime;
3255 std::optional<uint8_t> ipsExitUtil;
3256 std::optional<uint64_t> ipsExitTime;
3257
3258 if (!json_util::readJson(
3259 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3260 "EnterUtilizationPercent", ipsEnterUtil,
3261 "EnterDwellTimeSeconds", ipsEnterTime,
3262 "ExitUtilizationPercent", ipsExitUtil,
3263 "ExitDwellTimeSeconds", ipsExitTime))
3264 {
3265 return;
3266 }
3267 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3268 ipsEnterTime, ipsExitUtil, ipsExitTime);
3269 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003270 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003271}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303272
3273/**
3274 * SystemResetActionInfo derived class for delivering Computer Systems
3275 * ResetType AllowableValues using ResetInfo schema.
3276 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003277inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303278{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303279
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303280 /**
3281 * Functions triggers appropriate requests on DBus
3282 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003283 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003284 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003285 .methods(boost::beast::http::verb::get)(
3286 [](const crow::Request&,
3287 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3288 asyncResp->res.jsonValue = {
3289 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3290 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3291 {"Name", "Reset Action Info"},
3292 {"Id", "ResetActionInfo"},
3293 {"Parameters",
3294 {{{"Name", "ResetType"},
3295 {"Required", true},
3296 {"DataType", "String"},
3297 {"AllowableValues",
3298 {"On", "ForceOff", "ForceOn", "ForceRestart",
3299 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3300 "Nmi"}}}}}};
3301 });
3302}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003303} // namespace redfish