blob: b94612c2ffca7d3fc9fc047118b5df4c0eb4be32 [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 Tanoused398212021-06-09 17:05:54 -070025#include <registries/privilege_registry.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060026#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020027#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050028
Ed Tanousabf2add2019-01-22 16:40:12 -080029#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030
Ed Tanous1abe55e2018-09-05 08:30:59 -070031namespace redfish
32{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033
Alpana Kumari9d3ae102019-04-12 06:49:32 -050034/**
35 * @brief Updates the Functional State of DIMMs
36 *
37 * @param[in] aResp Shared pointer for completing asynchronous calls
38 * @param[in] dimmState Dimm's Functional state, true/false
39 *
40 * @return None.
41 */
zhanghch058d1b46d2021-04-01 11:18:24 +080042inline void
43 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
44 const std::variant<bool>& dimmState)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050045{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050046 const bool* isDimmFunctional = std::get_if<bool>(&dimmState);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050047 if (isDimmFunctional == nullptr)
48 {
49 messages::internalError(aResp->res);
50 return;
51 }
Gunnar Mills698654b2019-10-16 13:17:37 -050052 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050053
Gunnar Mills4e0453b2020-07-08 14:00:30 -050054 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055 // Update STATE only if previous State was DISABLED and current Dimm is
56 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050057 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050058 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
59 if (prevMemSummary == "Disabled")
60 {
61 if (*isDimmFunctional == true)
62 {
63 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
64 "Enabled";
65 }
66 }
67}
68
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050069/*
70 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
71 *
72 * @param[in] aResp Shared pointer for completing asynchronous calls
73 * @param[in] cpuPresenceState CPU present or not
74 *
75 * @return None.
76 */
zhanghch058d1b46d2021-04-01 11:18:24 +080077inline void
78 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
79 const std::variant<bool>& cpuPresenceState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050080{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050081 const bool* isCpuPresent = std::get_if<bool>(&cpuPresenceState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050082
83 if (isCpuPresent == nullptr)
84 {
85 messages::internalError(aResp->res);
86 return;
87 }
Gunnar Mills698654b2019-10-16 13:17:37 -050088 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050089
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050090 if (*isCpuPresent == true)
91 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050092 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080093 aResp->res.jsonValue["ProcessorSummary"]["Count"];
94 auto procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050095 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080096 if (procCountPtr != nullptr)
97 {
98 // shouldn't be possible to be nullptr
99 *procCountPtr += 1;
100 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500101 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500102}
103
104/*
105 * @brief Update "ProcessorSummary" "Status" "State" based on
106 * CPU Functional State
107 *
108 * @param[in] aResp Shared pointer for completing asynchronous calls
109 * @param[in] cpuFunctionalState is CPU functional true/false
110 *
111 * @return None.
112 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000113inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800114 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000115 const std::variant<bool>& cpuFunctionalState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500116{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500117 const bool* isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118
119 if (isCpuFunctional == nullptr)
120 {
121 messages::internalError(aResp->res);
122 return;
123 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500124 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500125
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500126 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500127 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
128
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500129 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500130 // Update STATE only if previous State was Non_Functional and current CPU is
131 // Functional.
132 if (prevProcState == "Disabled")
133 {
134 if (*isCpuFunctional == true)
135 {
136 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
137 "Enabled";
138 }
139 }
140}
141
Ali Ahmed03fbed92021-09-03 02:33:43 -0500142inline void getProcessorProperties(
143 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
144 const std::string& path,
145 const std::vector<std::pair<
146 std::string, std::variant<std::string, uint64_t, uint32_t, uint16_t>>>&
147 properties)
148{
149
150 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
151
152 auto getCpuPresenceState =
153 [aResp](const boost::system::error_code ec3,
154 const std::variant<bool>& cpuPresenceCheck) {
155 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,
165 const std::variant<bool>& cpuFunctionalCheck) {
166 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<
239 std::string, std::variant<std::string, uint64_t, uint32_t,
240 uint16_t>>>& properties) {
241 if (ec2)
242 {
243 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
244 messages::internalError(aResp->res);
245 return;
246 }
247 getProcessorProperties(aResp, service, path, properties);
248 },
249 service, path, "org.freedesktop.DBus.Properties", "GetAll",
250 "xyz.openbmc_project.Inventory.Item.Cpu");
251}
252
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500253/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700254 * @brief Retrieves computer system properties over dbus
255 *
256 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500257 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700258 *
259 * @return None.
260 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700261inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800262 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700263 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700264{
Ed Tanous6c34de42018-08-29 13:37:36 -0700265 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500266
Ed Tanous6c34de42018-08-29 13:37:36 -0700267 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700268 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700269 const boost::system::error_code ec,
270 const std::vector<std::pair<
271 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500272 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
273 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700274 if (ec)
275 {
276 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700277 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700278 return;
279 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700280 // Iterate over all retrieved ObjectPaths.
281 for (const std::pair<std::string,
282 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500283 std::string, std::vector<std::string>>>>&
284 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700285 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500286 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700287 BMCWEB_LOG_DEBUG << "Got path: " << path;
288 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500289 std::pair<std::string, std::vector<std::string>>>&
290 connectionNames = object.second;
Ed Tanous6c34de42018-08-29 13:37:36 -0700291 if (connectionNames.size() < 1)
292 {
293 continue;
294 }
Ed Tanous029573d2019-02-01 10:57:49 -0800295
James Feist5bc2dc82019-10-22 14:33:16 -0700296 auto memoryHealth = std::make_shared<HealthPopulate>(
297 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
298
299 auto cpuHealth = std::make_shared<HealthPopulate>(
300 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
301
302 systemHealth->children.emplace_back(memoryHealth);
303 systemHealth->children.emplace_back(cpuHealth);
304
Ed Tanous029573d2019-02-01 10:57:49 -0800305 // This is not system, so check if it's cpu, dimm, UUID or
306 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500307 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700308 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500309 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700310 {
Ed Tanous029573d2019-02-01 10:57:49 -0800311 if (interfaceName ==
312 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700313 {
Ed Tanous029573d2019-02-01 10:57:49 -0800314 BMCWEB_LOG_DEBUG
315 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500316
Ed Tanous029573d2019-02-01 10:57:49 -0800317 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500318 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700319 path](const boost::system::error_code ec2,
320 const std::vector<
321 std::pair<std::string, VariantType>>&
322 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 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500336 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500337 VariantType>&
338 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700339 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800340 if (property.first !=
341 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700342 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800343 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700344 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500345 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500346 std::get_if<uint32_t>(
347 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800348 if (value == nullptr)
349 {
350 BMCWEB_LOG_DEBUG
351 << "Find incorrect type of "
352 "MemorySize";
353 continue;
354 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500355 nlohmann::json& totalMemory =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800356 aResp->res
357 .jsonValue["MemorySummar"
358 "y"]
359 ["TotalSystemMe"
360 "moryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500361 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800362 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500363 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800364 if (preValue == nullptr)
365 {
366 continue;
367 }
368 aResp->res
369 .jsonValue["MemorySummary"]
370 ["TotalSystemMemoryGi"
371 "B"] =
372 *value / (1024 * 1024) +
373 *preValue;
374 aResp->res
375 .jsonValue["MemorySummary"]
376 ["Status"]["State"] =
377 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700378 }
Ed Tanous029573d2019-02-01 10:57:49 -0800379 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500380 else
381 {
382 auto getDimmProperties =
383 [aResp](
384 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000385 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500386 const std::variant<bool>&
387 dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000388 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500389 {
390 BMCWEB_LOG_ERROR
391 << "DBUS response "
392 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000393 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500394 return;
395 }
396 updateDimmProperties(aResp,
397 dimmState);
398 };
399 crow::connections::systemBus
400 ->async_method_call(
401 std::move(getDimmProperties),
402 service, path,
403 "org.freedesktop.DBus."
404 "Properties",
405 "Get",
406 "xyz.openbmc_project.State."
407 "Decorator.OperationalStatus",
408 "Functional");
409 }
Ed Tanous029573d2019-02-01 10:57:49 -0800410 },
411 connection.first, path,
412 "org.freedesktop.DBus.Properties", "GetAll",
413 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700414
415 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800416 }
417 else if (interfaceName ==
418 "xyz.openbmc_project.Inventory.Item.Cpu")
419 {
420 BMCWEB_LOG_DEBUG
421 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500422
Ali Ahmed03fbed92021-09-03 02:33:43 -0500423 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700424
425 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800426 }
427 else if (interfaceName ==
428 "xyz.openbmc_project.Common.UUID")
429 {
430 BMCWEB_LOG_DEBUG
431 << "Found UUID, now get its properties.";
432 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500433 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000434 const boost::system::error_code ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500435 const std::vector<
436 std::pair<std::string, VariantType>>&
437 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000438 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800439 {
440 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000441 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800442 messages::internalError(aResp->res);
443 return;
444 }
445 BMCWEB_LOG_DEBUG << "Got "
446 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500447 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800448 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500449 VariantType>&
450 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800451 {
Ed Tanous029573d2019-02-01 10:57:49 -0800452 if (property.first == "UUID")
453 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500454 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500455 std::get_if<std::string>(
456 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700457
Ed Tanous029573d2019-02-01 10:57:49 -0800458 if (value != nullptr)
459 {
460 std::string valueStr = *value;
461 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700462 {
Ed Tanous029573d2019-02-01 10:57:49 -0800463 valueStr.insert(8, 1, '-');
464 valueStr.insert(13, 1, '-');
465 valueStr.insert(18, 1, '-');
466 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700467 }
Ed Tanous029573d2019-02-01 10:57:49 -0800468 BMCWEB_LOG_DEBUG << "UUID = "
469 << valueStr;
470 aResp->res.jsonValue["UUID"] =
471 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700472 }
473 }
Ed Tanous029573d2019-02-01 10:57:49 -0800474 }
475 },
476 connection.first, path,
477 "org.freedesktop.DBus.Properties", "GetAll",
478 "xyz.openbmc_project.Common.UUID");
479 }
480 else if (interfaceName ==
481 "xyz.openbmc_project.Inventory.Item.System")
482 {
483 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500484 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000485 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500486 const std::vector<
487 std::pair<std::string, VariantType>>&
488 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000489 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800490 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700491 // doesn't have to include this
492 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800493 return;
494 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500495 BMCWEB_LOG_DEBUG
496 << "Got " << propertiesList.size()
497 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800498 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500499 VariantType>&
500 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800501 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500502 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600503 property.first;
504 if ((propertyName == "PartNumber") ||
505 (propertyName == "SerialNumber") ||
506 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500507 (propertyName == "Model") ||
508 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800509 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500510 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600511 std::get_if<std::string>(
512 &property.second);
513 if (value != nullptr)
514 {
515 aResp->res
516 .jsonValue[propertyName] =
517 *value;
518 }
Ed Tanous029573d2019-02-01 10:57:49 -0800519 }
520 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500521
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600522 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500523 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600524 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500525 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800526 },
527 connection.first, path,
528 "org.freedesktop.DBus.Properties", "GetAll",
529 "xyz.openbmc_project.Inventory.Decorator."
530 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700531
532 crow::connections::systemBus->async_method_call(
533 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000534 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500535 const std::variant<std::string>& property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000536 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700537 {
538 // doesn't have to include this
539 // interface
540 return;
541 }
542
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500543 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700544 std::get_if<std::string>(&property);
545 if (value != nullptr)
546 {
547 aResp->res.jsonValue["AssetTag"] =
548 *value;
549 }
550 },
551 connection.first, path,
552 "org.freedesktop.DBus.Properties", "Get",
553 "xyz.openbmc_project.Inventory.Decorator."
554 "AssetTag",
555 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700556 }
557 }
558 }
559 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700560 },
561 "xyz.openbmc_project.ObjectMapper",
562 "/xyz/openbmc_project/object_mapper",
563 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700564 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500565 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700566 "xyz.openbmc_project.Inventory.Decorator.Asset",
567 "xyz.openbmc_project.Inventory.Item.Cpu",
568 "xyz.openbmc_project.Inventory.Item.Dimm",
569 "xyz.openbmc_project.Inventory.Item.System",
570 "xyz.openbmc_project.Common.UUID",
571 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700572}
573
574/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700575 * @brief Retrieves host state properties over dbus
576 *
577 * @param[in] aResp Shared pointer for completing asynchronous calls.
578 *
579 * @return None.
580 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800581inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700582{
583 BMCWEB_LOG_DEBUG << "Get host information.";
584 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800585 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500586 const std::variant<std::string>& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700587 if (ec)
588 {
589 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700590 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700591 return;
592 }
Ed Tanous66173382018-08-15 18:20:59 -0700593
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500594 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700595 BMCWEB_LOG_DEBUG << "Host state: " << *s;
596 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700597 {
Ed Tanous66173382018-08-15 18:20:59 -0700598 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800599 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700600 {
Ed Tanous66173382018-08-15 18:20:59 -0700601 aResp->res.jsonValue["PowerState"] = "On";
602 aResp->res.jsonValue["Status"]["State"] = "Enabled";
603 }
Andrew Geissler83935af2020-02-13 10:24:53 -0600604 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Gunnar Mills8c888602020-05-01 14:25:09 -0500605 "Quiesced")
606 {
607 aResp->res.jsonValue["PowerState"] = "On";
608 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
609 }
610 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Andrew Geissler83935af2020-02-13 10:24:53 -0600611 "DiagnosticMode")
612 {
613 aResp->res.jsonValue["PowerState"] = "On";
614 aResp->res.jsonValue["Status"]["State"] = "InTest";
615 }
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600616 else if (*s == "xyz.openbmc_project.State.Host.HostState."
617 "TransitioningToRunning")
618 {
619 aResp->res.jsonValue["PowerState"] = "PoweringOn";
Noah Brewer15c27bf2021-04-27 15:24:25 -0500620 aResp->res.jsonValue["Status"]["State"] = "Starting";
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600621 }
622 else if (*s == "xyz.openbmc_project.State.Host.HostState."
623 "TransitioningToOff")
624 {
625 aResp->res.jsonValue["PowerState"] = "PoweringOff";
626 aResp->res.jsonValue["Status"]["State"] = "Disabled";
627 }
Ed Tanous66173382018-08-15 18:20:59 -0700628 else
629 {
630 aResp->res.jsonValue["PowerState"] = "Off";
631 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700632 }
633 }
634 },
635 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700636 "org.freedesktop.DBus.Properties", "Get",
637 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700638}
639
640/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500641 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530642 *
643 * @param[in] dbusSource The boot source in DBUS speak.
644 *
645 * @return Returns as a string, the boot source in Redfish terms. If translation
646 * cannot be done, returns an empty string.
647 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000648inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530649{
650 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
651 {
652 return "None";
653 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700654 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530655 {
656 return "Hdd";
657 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700658 if (dbusSource ==
659 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530660 {
661 return "Cd";
662 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700663 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530664 {
665 return "Pxe";
666 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700667 if (dbusSource ==
668 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700669 {
670 return "Usb";
671 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700672 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530673}
674
675/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300676 * @brief Translates boot type DBUS property value to redfish.
677 *
678 * @param[in] dbusType The boot type in DBUS speak.
679 *
680 * @return Returns as a string, the boot type in Redfish terms. If translation
681 * cannot be done, returns an empty string.
682 */
683inline std::string dbusToRfBootType(const std::string& dbusType)
684{
685 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
686 {
687 return "Legacy";
688 }
689 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
690 {
691 return "UEFI";
692 }
693 return "";
694}
695
696/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500697 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530698 *
699 * @param[in] dbusMode The boot mode in DBUS speak.
700 *
701 * @return Returns as a string, the boot mode in Redfish terms. If translation
702 * cannot be done, returns an empty string.
703 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000704inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530705{
706 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
707 {
708 return "None";
709 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700710 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530711 {
712 return "Diags";
713 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700714 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530715 {
716 return "BiosSetup";
717 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700718 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530719}
720
721/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500722 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530723 *
724 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700725 * @param[out] bootSource The DBus source
726 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530727 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700728 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530729 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800730inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500731 const std::string& rfSource,
732 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530733{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300734 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
735 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700736
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530737 if (rfSource == "None")
738 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700739 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530740 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700741 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530742 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700743 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
744 }
745 else if (rfSource == "Hdd")
746 {
747 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
748 }
749 else if (rfSource == "Diags")
750 {
751 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
752 }
753 else if (rfSource == "Cd")
754 {
755 bootSource =
756 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
757 }
758 else if (rfSource == "BiosSetup")
759 {
760 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530761 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700762 else if (rfSource == "Usb")
763 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700764 bootSource =
765 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700766 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530767 else
768 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700769 BMCWEB_LOG_DEBUG << "Invalid property value for "
770 "BootSourceOverrideTarget: "
771 << bootSource;
772 messages::propertyValueNotInList(aResp->res, rfSource,
773 "BootSourceTargetOverride");
774 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530775 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777}
Ali Ahmed19817712021-06-29 17:01:52 -0500778
Andrew Geissler978b8802020-11-19 13:36:40 -0600779/**
780 * @brief Retrieves boot progress of the system
781 *
782 * @param[in] aResp Shared pointer for generating response message.
783 *
784 * @return None.
785 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800786inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600787{
788 crow::connections::systemBus->async_method_call(
789 [aResp](const boost::system::error_code ec,
790 const std::variant<std::string>& bootProgress) {
791 if (ec)
792 {
793 // BootProgress is an optional object so just do nothing if
794 // not found
795 return;
796 }
797
798 const std::string* bootProgressStr =
799 std::get_if<std::string>(&bootProgress);
800
801 if (!bootProgressStr)
802 {
803 // Interface implemented but property not found, return error
804 // for that
805 messages::internalError(aResp->res);
806 return;
807 }
808
809 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
810
811 // Now convert the D-Bus BootProgress to the appropriate Redfish
812 // enum
813 std::string rfBpLastState = "None";
814 if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
815 "ProgressStages.Unspecified")
816 {
817 rfBpLastState = "None";
818 }
819 else if (*bootProgressStr ==
820 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
821 "PrimaryProcInit")
822 {
823 rfBpLastState = "PrimaryProcessorInitializationStarted";
824 }
825 else if (*bootProgressStr ==
826 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
827 "BusInit")
828 {
829 rfBpLastState = "BusInitializationStarted";
830 }
831 else if (*bootProgressStr ==
832 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
833 "MemoryInit")
834 {
835 rfBpLastState = "MemoryInitializationStarted";
836 }
837 else if (*bootProgressStr ==
838 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
839 "SecondaryProcInit")
840 {
841 rfBpLastState = "SecondaryProcessorInitializationStarted";
842 }
843 else if (*bootProgressStr ==
844 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
845 "PCIInit")
846 {
847 rfBpLastState = "PCIResourceConfigStarted";
848 }
849 else if (*bootProgressStr ==
850 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
851 "SystemInitComplete")
852 {
853 rfBpLastState = "SystemHardwareInitializationComplete";
854 }
855 else if (*bootProgressStr ==
856 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
857 "OSStart")
858 {
859 rfBpLastState = "OSBootStarted";
860 }
861 else if (*bootProgressStr ==
862 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
863 "OSRunning")
864 {
865 rfBpLastState = "OSRunning";
866 }
867 else
868 {
869 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
870 << *bootProgressStr;
871 // Just return the default
872 }
873
874 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
875 },
876 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
877 "org.freedesktop.DBus.Properties", "Get",
878 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
879}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530880
881/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300882 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300883 *
884 * @param[in] aResp Shared pointer for generating response message.
885 *
886 * @return None.
887 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300888
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300889inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300890{
891 crow::connections::systemBus->async_method_call(
892 [aResp](const boost::system::error_code ec,
893 const std::variant<std::string>& bootType) {
894 if (ec)
895 {
896 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300897 return;
898 }
899
900 const std::string* bootTypeStr =
901 std::get_if<std::string>(&bootType);
902
903 if (!bootTypeStr)
904 {
905 messages::internalError(aResp->res);
906 return;
907 }
908
909 BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
910
911 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode@Redfish."
912 "AllowableValues"] = {"Legacy",
913 "UEFI"};
914
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,
942 const std::variant<std::string>& 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
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530961 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
962 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700963 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530964
965 if (*bootModeStr !=
966 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
967 {
968 auto rfMode = dbusToRfBootMode(*bootModeStr);
969 if (!rfMode.empty())
970 {
971 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
972 rfMode;
973 }
974 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530975 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300976 "xyz.openbmc_project.Settings",
977 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530978 "org.freedesktop.DBus.Properties", "Get",
979 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
980}
981
982/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300983 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530984 *
985 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986 *
987 * @return None.
988 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300989
990inline void
991 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530992{
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530993 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300994 [aResp](const boost::system::error_code ec,
995 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530996 if (ec)
997 {
998 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
999 messages::internalError(aResp->res);
1000 return;
1001 }
1002
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001003 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301004 std::get_if<std::string>(&bootSource);
1005
1006 if (!bootSourceStr)
1007 {
1008 messages::internalError(aResp->res);
1009 return;
1010 }
1011 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1012
1013 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1014 if (!rfSource.empty())
1015 {
1016 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1017 rfSource;
1018 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001019
1020 // Get BootMode as BootSourceOverrideTarget is constructed
1021 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001022 getBootOverrideMode(aResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301023 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001024 "xyz.openbmc_project.Settings",
1025 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026 "org.freedesktop.DBus.Properties", "Get",
1027 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301028}
1029
1030/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001031 * @brief This functions abstracts all the logic behind getting a
1032 * "BootSourceOverrideEnabled" property from an overall boot override enable
1033 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034 *
1035 * @param[in] aResp Shared pointer for generating response message.
1036 *
1037 * @return None.
1038 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301039
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001040inline void
1041 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1042 const bool bootOverrideEnableSetting)
1043{
1044 if (!bootOverrideEnableSetting)
1045 {
1046 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1047 return;
1048 }
1049
1050 // If boot source override is enabled, we need to check 'one_time'
1051 // property to set a correct value for the "BootSourceOverrideEnabled"
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301052 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001053 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001054 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301055 if (ec)
1056 {
1057 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001058 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301059 return;
1060 }
1061
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001062 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301063
1064 if (!oneTimePtr)
1065 {
1066 messages::internalError(aResp->res);
1067 return;
1068 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001069
1070 bool oneTimeSetting = *oneTimePtr;
1071
1072 if (oneTimeSetting)
1073 {
1074 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1075 "Once";
1076 }
1077 else
1078 {
1079 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1080 "Continuous";
1081 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301082 },
1083 "xyz.openbmc_project.Settings",
1084 "/xyz/openbmc_project/control/host0/boot/one_time",
1085 "org.freedesktop.DBus.Properties", "Get",
1086 "xyz.openbmc_project.Object.Enable", "Enabled");
1087}
1088
1089/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001090 * @brief Retrieves boot override enable over DBUS
1091 *
1092 * @param[in] aResp Shared pointer for generating response message.
1093 *
1094 * @return None.
1095 */
1096
1097inline void
1098 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1099{
1100 crow::connections::systemBus->async_method_call(
1101 [aResp](const boost::system::error_code ec,
1102 const std::variant<bool>& bootOverrideEnable) {
1103 if (ec)
1104 {
1105 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1106 messages::internalError(aResp->res);
1107 return;
1108 }
1109
1110 const bool* bootOverrideEnablePtr =
1111 std::get_if<bool>(&bootOverrideEnable);
1112
1113 if (!bootOverrideEnablePtr)
1114 {
1115 messages::internalError(aResp->res);
1116 return;
1117 }
1118
1119 processBootOverrideEnable(aResp, *bootOverrideEnablePtr);
1120 },
1121 "xyz.openbmc_project.Settings",
1122 "/xyz/openbmc_project/control/host0/boot",
1123 "org.freedesktop.DBus.Properties", "Get",
1124 "xyz.openbmc_project.Object.Enable", "Enabled");
1125}
1126
1127/**
1128 * @brief Retrieves boot source override properties
1129 *
1130 * @param[in] aResp Shared pointer for generating response message.
1131 *
1132 * @return None.
1133 */
1134inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1135{
1136 BMCWEB_LOG_DEBUG << "Get boot information.";
1137
1138 getBootOverrideSource(aResp);
1139 getBootOverrideType(aResp);
1140 getBootOverrideEnable(aResp);
1141}
1142
1143/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001144 * @brief Retrieves the Last Reset Time
1145 *
1146 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1147 * and power off. Even though this is the "system" Redfish object look at the
1148 * chassis D-Bus interface for the LastStateChangeTime since this has the
1149 * last power operation time.
1150 *
1151 * @param[in] aResp Shared pointer for generating response message.
1152 *
1153 * @return None.
1154 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001155inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001156{
1157 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1158
1159 crow::connections::systemBus->async_method_call(
1160 [aResp](const boost::system::error_code ec,
1161 std::variant<uint64_t>& lastResetTime) {
1162 if (ec)
1163 {
1164 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1165 return;
1166 }
1167
1168 const uint64_t* lastResetTimePtr =
1169 std::get_if<uint64_t>(&lastResetTime);
1170
1171 if (!lastResetTimePtr)
1172 {
1173 messages::internalError(aResp->res);
1174 return;
1175 }
1176 // LastStateChangeTime is epoch time, in milliseconds
1177 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1178 time_t lastResetTimeStamp =
1179 static_cast<time_t>(*lastResetTimePtr / 1000);
1180
1181 // Convert to ISO 8601 standard
1182 aResp->res.jsonValue["LastResetTime"] =
1183 crow::utility::getDateTime(lastResetTimeStamp);
1184 },
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,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001204 std::variant<bool>& 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,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001229 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001230 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001231 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001232 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001233 return;
1234 }
1235
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001236 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001237 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1238
1239 if (!autoRebootAttemptsLeftPtr)
1240 {
1241 messages::internalError(aResp->res);
1242 return;
1243 }
1244
1245 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1246 << *autoRebootAttemptsLeftPtr;
1247
1248 aResp->res
1249 .jsonValue["Boot"]
1250 ["RemainingAutomaticRetryAttempts"] =
1251 *autoRebootAttemptsLeftPtr;
1252 },
1253 "xyz.openbmc_project.State.Host",
1254 "/xyz/openbmc_project/state/host0",
1255 "org.freedesktop.DBus.Properties", "Get",
1256 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1257 "AttemptsLeft");
1258 }
1259 else
1260 {
1261 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1262 "Disabled";
1263 }
1264
1265 // Not on D-Bus. Hardcoded here:
1266 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1267 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001268
1269 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1270 // and RetryAttempts. OpenBMC only supports Disabled and
1271 // RetryAttempts.
1272 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1273 "AllowableValues"] = {"Disabled",
1274 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001275 },
1276 "xyz.openbmc_project.Settings",
1277 "/xyz/openbmc_project/control/host0/auto_reboot",
1278 "org.freedesktop.DBus.Properties", "Get",
1279 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1280}
1281
1282/**
George Liuc6a620f2020-04-10 17:18:11 +08001283 * @brief Retrieves power restore policy over DBUS.
1284 *
1285 * @param[in] aResp Shared pointer for generating response message.
1286 *
1287 * @return None.
1288 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001289inline void
1290 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001291{
1292 BMCWEB_LOG_DEBUG << "Get power restore policy";
1293
1294 crow::connections::systemBus->async_method_call(
1295 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001296 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001297 if (ec)
1298 {
1299 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1300 return;
1301 }
1302
1303 const boost::container::flat_map<std::string, std::string>
1304 policyMaps = {
1305 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1306 "AlwaysOn",
1307 "AlwaysOn"},
1308 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1309 "AlwaysOff",
1310 "AlwaysOff"},
1311 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001312 "Restore",
George Liuc6a620f2020-04-10 17:18:11 +08001313 "LastState"}};
1314
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001315 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001316
1317 if (!policyPtr)
1318 {
1319 messages::internalError(aResp->res);
1320 return;
1321 }
1322
1323 auto policyMapsIt = policyMaps.find(*policyPtr);
1324 if (policyMapsIt == policyMaps.end())
1325 {
1326 messages::internalError(aResp->res);
1327 return;
1328 }
1329
1330 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1331 },
1332 "xyz.openbmc_project.Settings",
1333 "/xyz/openbmc_project/control/host0/power_restore_policy",
1334 "org.freedesktop.DBus.Properties", "Get",
1335 "xyz.openbmc_project.Control.Power.RestorePolicy",
1336 "PowerRestorePolicy");
1337}
1338
1339/**
Ali Ahmed19817712021-06-29 17:01:52 -05001340 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1341 * TPM is required for booting the host.
1342 *
1343 * @param[in] aResp Shared pointer for generating response message.
1344 *
1345 * @return None.
1346 */
1347inline void getTrustedModuleRequiredToBoot(
1348 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1349{
1350 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1351
1352 crow::connections::systemBus->async_method_call(
1353 [aResp](
1354 const boost::system::error_code ec,
1355 std::vector<std::pair<
1356 std::string,
1357 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1358 subtree) {
1359 if (ec)
1360 {
1361 BMCWEB_LOG_DEBUG
1362 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1363 // This is an optional D-Bus object so just return if
1364 // error occurs
1365 return;
1366 }
1367 if (subtree.size() == 0)
1368 {
1369 // As noted above, this is an optional interface so just return
1370 // if there is no instance found
1371 return;
1372 }
1373
1374 /* When there is more than one TPMEnable object... */
1375 if (subtree.size() > 1)
1376 {
1377 BMCWEB_LOG_DEBUG
1378 << "DBUS response has more than 1 TPM Enable object:"
1379 << subtree.size();
1380 // Throw an internal Error and return
1381 messages::internalError(aResp->res);
1382 return;
1383 }
1384
1385 // Make sure the Dbus response map has a service and objectPath
1386 // field
1387 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1388 {
1389 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1390 messages::internalError(aResp->res);
1391 return;
1392 }
1393
1394 const std::string& path = subtree[0].first;
1395 const std::string& serv = subtree[0].second.begin()->first;
1396
1397 // Valid TPM Enable object found, now reading the current value
1398 crow::connections::systemBus->async_method_call(
1399 [aResp](const boost::system::error_code ec,
1400 std::variant<bool>& tpmRequired) {
1401 if (ec)
1402 {
1403 BMCWEB_LOG_DEBUG
1404 << "D-BUS response error on TPM.Policy Get" << ec;
1405 messages::internalError(aResp->res);
1406 return;
1407 }
1408
1409 const bool* tpmRequiredVal =
1410 std::get_if<bool>(&tpmRequired);
1411
1412 if (!tpmRequiredVal)
1413 {
1414 messages::internalError(aResp->res);
1415 return;
1416 }
1417
1418 if (*tpmRequiredVal == true)
1419 {
1420 aResp->res
1421 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1422 "Required";
1423 }
1424 else
1425 {
1426 aResp->res
1427 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1428 "Disabled";
1429 }
1430 },
1431 serv, path, "org.freedesktop.DBus.Properties", "Get",
1432 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1433 },
1434 "xyz.openbmc_project.ObjectMapper",
1435 "/xyz/openbmc_project/object_mapper",
1436 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1437 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1438}
1439
1440/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001441 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1442 * TPM is required for booting the host.
1443 *
1444 * @param[in] aResp Shared pointer for generating response message.
1445 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1446 *
1447 * @return None.
1448 */
1449inline void setTrustedModuleRequiredToBoot(
1450 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1451{
1452 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1453
1454 crow::connections::systemBus->async_method_call(
1455 [aResp, tpmRequired](
1456 const boost::system::error_code ec,
1457 std::vector<std::pair<
1458 std::string,
1459 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1460 subtree) {
1461 if (ec)
1462 {
1463 BMCWEB_LOG_DEBUG
1464 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1465 messages::internalError(aResp->res);
1466 return;
1467 }
1468 if (subtree.size() == 0)
1469 {
1470 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1471 "TrustedModuleRequiredToBoot");
1472 return;
1473 }
1474
1475 /* When there is more than one TPMEnable object... */
1476 if (subtree.size() > 1)
1477 {
1478 BMCWEB_LOG_DEBUG
1479 << "DBUS response has more than 1 TPM Enable object:"
1480 << subtree.size();
1481 // Throw an internal Error and return
1482 messages::internalError(aResp->res);
1483 return;
1484 }
1485
1486 // Make sure the Dbus response map has a service and objectPath
1487 // field
1488 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1489 {
1490 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1491 messages::internalError(aResp->res);
1492 return;
1493 }
1494
1495 const std::string& path = subtree[0].first;
1496 const std::string& serv = subtree[0].second.begin()->first;
1497
1498 if (serv.empty())
1499 {
1500 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1501 messages::internalError(aResp->res);
1502 return;
1503 }
1504
1505 // Valid TPM Enable object found, now setting the value
1506 crow::connections::systemBus->async_method_call(
1507 [aResp](const boost::system::error_code ec) {
1508 if (ec)
1509 {
1510 BMCWEB_LOG_DEBUG << "DBUS response error: Set "
1511 "TrustedModuleRequiredToBoot"
1512 << ec;
1513 messages::internalError(aResp->res);
1514 return;
1515 }
1516 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1517 },
1518 serv, path, "org.freedesktop.DBus.Properties", "Set",
1519 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1520 std::variant<bool>(tpmRequired));
1521 },
1522 "xyz.openbmc_project.ObjectMapper",
1523 "/xyz/openbmc_project/object_mapper",
1524 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1525 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1526}
1527
1528/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301529 * @brief Sets boot properties into DBUS object(s).
1530 *
1531 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001532 * @param[in] bootType The boot type to set.
1533 * @return Integer error code.
1534 */
1535inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001536 const std::optional<std::string>& bootType)
1537{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001538 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001539
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001540 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001541 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001542 return;
1543 }
1544
1545 // Source target specified
1546 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1547 // Figure out which DBUS interface and property to use
1548 if (*bootType == "Legacy")
1549 {
1550 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1551 }
1552 else if (*bootType == "UEFI")
1553 {
1554 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1555 }
1556 else
1557 {
1558 BMCWEB_LOG_DEBUG << "Invalid property value for "
1559 "BootSourceOverrideMode: "
1560 << *bootType;
1561 messages::propertyValueNotInList(aResp->res, *bootType,
1562 "BootSourceOverrideMode");
1563 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001564 }
1565
1566 // Act on validated parameters
1567 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1568
1569 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001570 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001571 if (ec)
1572 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001573 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1574 if (ec.value() == boost::asio::error::host_unreachable)
1575 {
1576 messages::resourceNotFound(aResp->res, "Set", "BootType");
1577 return;
1578 }
1579 messages::internalError(aResp->res);
1580 return;
1581 }
1582 BMCWEB_LOG_DEBUG << "Boot type update done.";
1583 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001584 "xyz.openbmc_project.Settings",
1585 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001586 "org.freedesktop.DBus.Properties", "Set",
1587 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1588 std::variant<std::string>(bootTypeStr));
1589}
1590
1591/**
1592 * @brief Sets boot properties into DBUS object(s).
1593 *
1594 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001595 * @param[in] bootType The boot type to set.
1596 * @return Integer error code.
1597 */
1598inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1599 const std::optional<std::string>& bootEnable)
1600{
1601 if (!bootEnable)
1602 {
1603 return;
1604 }
1605 // Source target specified
1606 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1607
1608 bool bootOverrideEnable = false;
1609 bool bootOverridePersistent = false;
1610 // Figure out which DBUS interface and property to use
1611 if (*bootEnable == "Disabled")
1612 {
1613 bootOverrideEnable = false;
1614 }
1615 else if (*bootEnable == "Once")
1616 {
1617 bootOverrideEnable = true;
1618 bootOverridePersistent = false;
1619 }
1620 else if (*bootEnable == "Continuous")
1621 {
1622 bootOverrideEnable = true;
1623 bootOverridePersistent = true;
1624 }
1625 else
1626 {
1627 BMCWEB_LOG_DEBUG << "Invalid property value for "
1628 "BootSourceOverrideEnabled: "
1629 << *bootEnable;
1630 messages::propertyValueNotInList(aResp->res, *bootEnable,
1631 "BootSourceOverrideEnabled");
1632 return;
1633 }
1634
1635 // Act on validated parameters
1636 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1637
1638 crow::connections::systemBus->async_method_call(
1639 [aResp](const boost::system::error_code ec) {
1640 if (ec)
1641 {
1642 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1643 messages::internalError(aResp->res);
1644 return;
1645 }
1646 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1647 },
1648 "xyz.openbmc_project.Settings",
1649 "/xyz/openbmc_project/control/host0/boot",
1650 "org.freedesktop.DBus.Properties", "Set",
1651 "xyz.openbmc_project.Object.Enable", "Enabled",
1652 std::variant<bool>(bootOverrideEnable));
1653
1654 if (!bootOverrideEnable)
1655 {
1656 return;
1657 }
1658
1659 // In case boot override is enabled we need to set correct value for the
1660 // 'one_time' enable DBus interface
1661 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1662 << bootOverridePersistent;
1663
1664 crow::connections::systemBus->async_method_call(
1665 [aResp](const boost::system::error_code ec) {
1666 if (ec)
1667 {
1668 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1669 messages::internalError(aResp->res);
1670 return;
1671 }
1672 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1673 },
1674 "xyz.openbmc_project.Settings",
1675 "/xyz/openbmc_project/control/host0/boot/one_time",
1676 "org.freedesktop.DBus.Properties", "Set",
1677 "xyz.openbmc_project.Object.Enable", "Enabled",
1678 std::variant<bool>(!bootOverridePersistent));
1679}
1680
1681/**
1682 * @brief Sets boot properties into DBUS object(s).
1683 *
1684 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301685 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301686 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001687 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301688 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001689inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001690 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301691{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001692 std::string bootSourceStr;
1693 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001694
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001695 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301696 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001697 return;
1698 }
1699
1700 // Source target specified
1701 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1702 // Figure out which DBUS interface and property to use
1703 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1704 {
1705 BMCWEB_LOG_DEBUG
1706 << "Invalid property value for BootSourceOverrideTarget: "
1707 << *bootSource;
1708 messages::propertyValueNotInList(aResp->res, *bootSource,
1709 "BootSourceTargetOverride");
1710 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001711 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301712
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001713 // Act on validated parameters
1714 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1715 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001716
1717 crow::connections::systemBus->async_method_call(
1718 [aResp](const boost::system::error_code ec) {
1719 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301720 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001721 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1722 messages::internalError(aResp->res);
1723 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301724 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001725 BMCWEB_LOG_DEBUG << "Boot source update done.";
1726 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001727 "xyz.openbmc_project.Settings",
1728 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001729 "org.freedesktop.DBus.Properties", "Set",
1730 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1731 std::variant<std::string>(bootSourceStr));
1732
1733 crow::connections::systemBus->async_method_call(
1734 [aResp](const boost::system::error_code ec) {
1735 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301736 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001737 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1738 messages::internalError(aResp->res);
1739 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301740 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001741 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1742 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001743 "xyz.openbmc_project.Settings",
1744 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001745 "org.freedesktop.DBus.Properties", "Set",
1746 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1747 std::variant<std::string>(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001748}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001749
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001750/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001751 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301752 *
1753 * @param[in] aResp Shared pointer for generating response message.
1754 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001755 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301756 * @param[in] bootEnable The boot override enable from incoming RF request.
1757 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001758 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301759 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001760
1761inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1762 const std::optional<std::string>& bootSource,
1763 const std::optional<std::string>& bootType,
1764 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301765{
1766 BMCWEB_LOG_DEBUG << "Set boot information.";
1767
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001768 setBootModeOrSource(aResp, bootSource);
1769 setBootType(aResp, bootType);
1770 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301771}
1772
George Liuc6a620f2020-04-10 17:18:11 +08001773/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001774 * @brief Sets AssetTag
1775 *
1776 * @param[in] aResp Shared pointer for generating response message.
1777 * @param[in] assetTag "AssetTag" from request.
1778 *
1779 * @return None.
1780 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001781inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001782 const std::string& assetTag)
1783{
1784 crow::connections::systemBus->async_method_call(
1785 [aResp, assetTag](
1786 const boost::system::error_code ec,
1787 const std::vector<std::pair<
1788 std::string,
1789 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1790 subtree) {
1791 if (ec)
1792 {
1793 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1794 messages::internalError(aResp->res);
1795 return;
1796 }
1797 if (subtree.size() == 0)
1798 {
1799 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1800 messages::internalError(aResp->res);
1801 return;
1802 }
1803 // Assume only 1 system D-Bus object
1804 // Throw an error if there is more than 1
1805 if (subtree.size() > 1)
1806 {
1807 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1808 messages::internalError(aResp->res);
1809 return;
1810 }
1811 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1812 {
1813 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1814 messages::internalError(aResp->res);
1815 return;
1816 }
1817
1818 const std::string& path = subtree[0].first;
1819 const std::string& service = subtree[0].second.begin()->first;
1820
1821 if (service.empty())
1822 {
1823 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1824 messages::internalError(aResp->res);
1825 return;
1826 }
1827
1828 crow::connections::systemBus->async_method_call(
1829 [aResp](const boost::system::error_code ec2) {
1830 if (ec2)
1831 {
1832 BMCWEB_LOG_DEBUG
1833 << "D-Bus response error on AssetTag Set " << ec2;
1834 messages::internalError(aResp->res);
1835 return;
1836 }
1837 },
1838 service, path, "org.freedesktop.DBus.Properties", "Set",
1839 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1840 std::variant<std::string>(assetTag));
1841 },
1842 "xyz.openbmc_project.ObjectMapper",
1843 "/xyz/openbmc_project/object_mapper",
1844 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1845 "/xyz/openbmc_project/inventory", int32_t(0),
1846 std::array<const char*, 1>{
1847 "xyz.openbmc_project.Inventory.Item.System"});
1848}
1849
1850/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001851 * @brief Sets automaticRetry (Auto Reboot)
1852 *
1853 * @param[in] aResp Shared pointer for generating response message.
1854 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1855 *
1856 * @return None.
1857 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001858inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001859 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001860{
1861 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1862
1863 // OpenBMC only supports "Disabled" and "RetryAttempts".
1864 bool autoRebootEnabled;
1865
1866 if (automaticRetryConfig == "Disabled")
1867 {
1868 autoRebootEnabled = false;
1869 }
1870 else if (automaticRetryConfig == "RetryAttempts")
1871 {
1872 autoRebootEnabled = true;
1873 }
1874 else
1875 {
1876 BMCWEB_LOG_DEBUG << "Invalid property value for "
1877 "AutomaticRetryConfig: "
1878 << automaticRetryConfig;
1879 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1880 "AutomaticRetryConfig");
1881 return;
1882 }
1883
1884 crow::connections::systemBus->async_method_call(
1885 [aResp](const boost::system::error_code ec) {
1886 if (ec)
1887 {
1888 messages::internalError(aResp->res);
1889 return;
1890 }
1891 },
1892 "xyz.openbmc_project.Settings",
1893 "/xyz/openbmc_project/control/host0/auto_reboot",
1894 "org.freedesktop.DBus.Properties", "Set",
1895 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1896 std::variant<bool>(autoRebootEnabled));
1897}
1898
1899/**
George Liuc6a620f2020-04-10 17:18:11 +08001900 * @brief Sets power restore policy properties.
1901 *
1902 * @param[in] aResp Shared pointer for generating response message.
1903 * @param[in] policy power restore policy properties from request.
1904 *
1905 * @return None.
1906 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001907inline void
1908 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1909 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001910{
1911 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1912
1913 const boost::container::flat_map<std::string, std::string> policyMaps = {
1914 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1915 "AlwaysOn"},
1916 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1917 "AlwaysOff"},
1918 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001919 "Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001920
1921 std::string powerRestorPolicy;
1922
Gunnar Mills4e69c902021-01-05 19:50:11 -06001923 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001924 if (policyMapsIt == policyMaps.end())
1925 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001926 messages::propertyValueNotInList(aResp->res, policy,
1927 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001928 return;
1929 }
1930
1931 powerRestorPolicy = policyMapsIt->second;
1932
1933 crow::connections::systemBus->async_method_call(
1934 [aResp](const boost::system::error_code ec) {
1935 if (ec)
1936 {
1937 messages::internalError(aResp->res);
1938 return;
1939 }
1940 },
1941 "xyz.openbmc_project.Settings",
1942 "/xyz/openbmc_project/control/host0/power_restore_policy",
1943 "org.freedesktop.DBus.Properties", "Set",
1944 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1945 std::variant<std::string>(powerRestorPolicy));
1946}
1947
AppaRao Pulia6349912019-10-18 17:16:08 +05301948#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1949/**
1950 * @brief Retrieves provisioning status
1951 *
1952 * @param[in] aResp Shared pointer for completing asynchronous calls.
1953 *
1954 * @return None.
1955 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001956inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301957{
1958 BMCWEB_LOG_DEBUG << "Get OEM information.";
1959 crow::connections::systemBus->async_method_call(
1960 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001961 const std::vector<std::pair<std::string, VariantType>>&
1962 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301963 nlohmann::json& oemPFR =
1964 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001965 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1966 "#OemComputerSystem.OpenBmc";
1967 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1968
AppaRao Pulia6349912019-10-18 17:16:08 +05301969 if (ec)
1970 {
1971 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301972 // not an error, don't have to have the interface
1973 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301974 return;
1975 }
1976
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001977 const bool* provState = nullptr;
1978 const bool* lockState = nullptr;
1979 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301980 propertiesList)
1981 {
1982 if (property.first == "UfmProvisioned")
1983 {
1984 provState = std::get_if<bool>(&property.second);
1985 }
1986 else if (property.first == "UfmLocked")
1987 {
1988 lockState = std::get_if<bool>(&property.second);
1989 }
1990 }
1991
1992 if ((provState == nullptr) || (lockState == nullptr))
1993 {
1994 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1995 messages::internalError(aResp->res);
1996 return;
1997 }
1998
AppaRao Pulia6349912019-10-18 17:16:08 +05301999 if (*provState == true)
2000 {
2001 if (*lockState == true)
2002 {
2003 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
2004 }
2005 else
2006 {
2007 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
2008 }
2009 }
2010 else
2011 {
2012 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2013 }
2014 },
2015 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2016 "org.freedesktop.DBus.Properties", "GetAll",
2017 "xyz.openbmc_project.PFR.Attributes");
2018}
2019#endif
2020
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302021/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002022 * @brief Translate the PowerMode to a response message.
2023 *
2024 * @param[in] aResp Shared pointer for generating response message.
2025 * @param[in] modeValue PowerMode value to be translated
2026 *
2027 * @return None.
2028 */
2029inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2030 const std::string& modeValue)
2031{
2032 std::string modeString;
2033
2034 if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2035 "PowerMode.Static")
2036 {
2037 aResp->res.jsonValue["PowerMode"] = "Static";
2038 }
2039 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2040 "PowerMode.MaximumPerformance")
2041 {
2042 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2043 }
2044 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2045 "PowerMode.PowerSaving")
2046 {
2047 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2048 }
2049 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2050 "PowerMode.OEM")
2051 {
2052 aResp->res.jsonValue["PowerMode"] = "OEM";
2053 }
2054 else
2055 {
2056 // Any other values would be invalid
2057 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2058 messages::internalError(aResp->res);
2059 }
2060}
2061
2062/**
2063 * @brief Retrieves system power mode
2064 *
2065 * @param[in] aResp Shared pointer for generating response message.
2066 *
2067 * @return None.
2068 */
2069inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2070{
2071 BMCWEB_LOG_DEBUG << "Get power mode.";
2072
2073 // Get Power Mode object path:
2074 crow::connections::systemBus->async_method_call(
2075 [aResp](
2076 const boost::system::error_code ec,
2077 const std::vector<std::pair<
2078 std::string,
2079 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2080 subtree) {
2081 if (ec)
2082 {
2083 BMCWEB_LOG_DEBUG
2084 << "DBUS response error on Power.Mode GetSubTree " << ec;
2085 // This is an optional D-Bus object so just return if
2086 // error occurs
2087 return;
2088 }
2089 if (subtree.empty())
2090 {
2091 // As noted above, this is an optional interface so just return
2092 // if there is no instance found
2093 return;
2094 }
2095 if (subtree.size() > 1)
2096 {
2097 // More then one PowerMode object is not supported and is an
2098 // error
2099 BMCWEB_LOG_DEBUG
2100 << "Found more than 1 system D-Bus Power.Mode objects: "
2101 << subtree.size();
2102 messages::internalError(aResp->res);
2103 return;
2104 }
2105 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2106 {
2107 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2108 messages::internalError(aResp->res);
2109 return;
2110 }
2111 const std::string& path = subtree[0].first;
2112 const std::string& service = subtree[0].second.begin()->first;
2113 if (service.empty())
2114 {
2115 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2116 messages::internalError(aResp->res);
2117 return;
2118 }
2119 // Valid Power Mode object found, now read the current value
2120 crow::connections::systemBus->async_method_call(
2121 [aResp](const boost::system::error_code ec,
2122 const std::variant<std::string>& pmode) {
2123 if (ec)
2124 {
2125 BMCWEB_LOG_DEBUG
2126 << "DBUS response error on PowerMode Get: " << ec;
2127 messages::internalError(aResp->res);
2128 return;
2129 }
2130
2131 const std::string* s = std::get_if<std::string>(&pmode);
2132 if (s == nullptr)
2133 {
2134 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2135 messages::internalError(aResp->res);
2136 return;
2137 }
2138
2139 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2140 {"Static", "MaximumPerformance", "PowerSaving"};
2141
2142 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2143 translatePowerMode(aResp, *s);
2144 },
2145 service, path, "org.freedesktop.DBus.Properties", "Get",
2146 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2147 },
2148 "xyz.openbmc_project.ObjectMapper",
2149 "/xyz/openbmc_project/object_mapper",
2150 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2151 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2152}
2153
2154/**
2155 * @brief Validate the specified mode is valid and return the PowerMode
2156 * name associated with that string
2157 *
2158 * @param[in] aResp Shared pointer for generating response message.
2159 * @param[in] modeString String representing the desired PowerMode
2160 *
2161 * @return PowerMode value or empty string if mode is not valid
2162 */
2163inline std::string
2164 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2165 const std::string& modeString)
2166{
2167 std::string mode;
2168
2169 if (modeString == "Static")
2170 {
2171 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2172 }
2173 else if (modeString == "MaximumPerformance")
2174 {
2175 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
2176 "MaximumPerformance";
2177 }
2178 else if (modeString == "PowerSaving")
2179 {
2180 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2181 }
2182 else
2183 {
2184 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2185 }
2186 return mode;
2187}
2188
2189/**
2190 * @brief Sets system power mode.
2191 *
2192 * @param[in] aResp Shared pointer for generating response message.
2193 * @param[in] pmode System power mode from request.
2194 *
2195 * @return None.
2196 */
2197inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2198 const std::string& pmode)
2199{
2200 BMCWEB_LOG_DEBUG << "Set power mode.";
2201
2202 std::string powerMode = validatePowerMode(aResp, pmode);
2203 if (powerMode.empty())
2204 {
2205 return;
2206 }
2207
2208 // Get Power Mode object path:
2209 crow::connections::systemBus->async_method_call(
2210 [aResp, powerMode](
2211 const boost::system::error_code ec,
2212 const std::vector<std::pair<
2213 std::string,
2214 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2215 subtree) {
2216 if (ec)
2217 {
2218 BMCWEB_LOG_DEBUG
2219 << "DBUS response error on Power.Mode GetSubTree " << ec;
2220 // This is an optional D-Bus object, but user attempted to patch
2221 messages::internalError(aResp->res);
2222 return;
2223 }
2224 if (subtree.empty())
2225 {
2226 // This is an optional D-Bus object, but user attempted to patch
2227 messages::resourceNotFound(aResp->res, "ComputerSystem",
2228 "PowerMode");
2229 return;
2230 }
2231 if (subtree.size() > 1)
2232 {
2233 // More then one PowerMode object is not supported and is an
2234 // error
2235 BMCWEB_LOG_DEBUG
2236 << "Found more than 1 system D-Bus Power.Mode objects: "
2237 << subtree.size();
2238 messages::internalError(aResp->res);
2239 return;
2240 }
2241 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2242 {
2243 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2244 messages::internalError(aResp->res);
2245 return;
2246 }
2247 const std::string& path = subtree[0].first;
2248 const std::string& service = subtree[0].second.begin()->first;
2249 if (service.empty())
2250 {
2251 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2252 messages::internalError(aResp->res);
2253 return;
2254 }
2255
2256 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2257 << path;
2258
2259 // Set the Power Mode property
2260 crow::connections::systemBus->async_method_call(
2261 [aResp](const boost::system::error_code ec) {
2262 if (ec)
2263 {
2264 messages::internalError(aResp->res);
2265 return;
2266 }
2267 },
2268 service, path, "org.freedesktop.DBus.Properties", "Set",
2269 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2270 std::variant<std::string>(powerMode));
2271 },
2272 "xyz.openbmc_project.ObjectMapper",
2273 "/xyz/openbmc_project/object_mapper",
2274 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2275 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2276}
2277
2278/**
Yong Li51709ff2019-09-30 14:13:04 +08002279 * @brief Translates watchdog timeout action DBUS property value to redfish.
2280 *
2281 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2282 *
2283 * @return Returns as a string, the timeout action in Redfish terms. If
2284 * translation cannot be done, returns an empty string.
2285 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002286inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002287{
2288 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2289 {
2290 return "None";
2291 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002292 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002293 {
2294 return "ResetSystem";
2295 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002296 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002297 {
2298 return "PowerDown";
2299 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002300 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002301 {
2302 return "PowerCycle";
2303 }
2304
2305 return "";
2306}
2307
2308/**
Yong Lic45f0082019-10-10 14:19:01 +08002309 *@brief Translates timeout action from Redfish to DBUS property value.
2310 *
2311 *@param[in] rfAction The timeout action in Redfish.
2312 *
2313 *@return Returns as a string, the time_out action as expected by DBUS.
2314 *If translation cannot be done, returns an empty string.
2315 */
2316
Ed Tanous23a21a12020-07-25 04:45:05 +00002317inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002318{
2319 if (rfAction == "None")
2320 {
2321 return "xyz.openbmc_project.State.Watchdog.Action.None";
2322 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002323 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002324 {
2325 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2326 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002327 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002328 {
2329 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2330 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002331 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002332 {
2333 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2334 }
2335
2336 return "";
2337}
2338
2339/**
Yong Li51709ff2019-09-30 14:13:04 +08002340 * @brief Retrieves host watchdog timer properties over DBUS
2341 *
2342 * @param[in] aResp Shared pointer for completing asynchronous calls.
2343 *
2344 * @return None.
2345 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002346inline void
2347 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002348{
2349 BMCWEB_LOG_DEBUG << "Get host watchodg";
2350 crow::connections::systemBus->async_method_call(
2351 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002352 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002353 if (ec)
2354 {
2355 // watchdog service is stopped
2356 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2357 return;
2358 }
2359
2360 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2361
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002362 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002363 aResp->res.jsonValue["HostWatchdogTimer"];
2364
2365 // watchdog service is running/enabled
2366 hostWatchdogTimer["Status"]["State"] = "Enabled";
2367
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002368 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002369 {
2370 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2371 if (property.first == "Enabled")
2372 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002373 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002374
2375 if (!state)
2376 {
2377 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002378 return;
Yong Li51709ff2019-09-30 14:13:04 +08002379 }
2380
2381 hostWatchdogTimer["FunctionEnabled"] = *state;
2382 }
2383 else if (property.first == "ExpireAction")
2384 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002385 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002386 std::get_if<std::string>(&property.second);
2387 if (!s)
2388 {
2389 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002390 return;
Yong Li51709ff2019-09-30 14:13:04 +08002391 }
2392
2393 std::string action = dbusToRfWatchdogAction(*s);
2394 if (action.empty())
2395 {
2396 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002397 return;
Yong Li51709ff2019-09-30 14:13:04 +08002398 }
2399 hostWatchdogTimer["TimeoutAction"] = action;
2400 }
2401 }
2402 },
2403 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2404 "org.freedesktop.DBus.Properties", "GetAll",
2405 "xyz.openbmc_project.State.Watchdog");
2406}
2407
2408/**
Yong Lic45f0082019-10-10 14:19:01 +08002409 * @brief Sets Host WatchDog Timer properties.
2410 *
2411 * @param[in] aResp Shared pointer for generating response message.
2412 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2413 * RF request.
2414 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2415 *
2416 * @return None.
2417 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002418inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002419 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002420 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002421{
2422 BMCWEB_LOG_DEBUG << "Set host watchdog";
2423
2424 if (wdtTimeOutAction)
2425 {
2426 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2427 // check if TimeOut Action is Valid
2428 if (wdtTimeOutActStr.empty())
2429 {
2430 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2431 << *wdtTimeOutAction;
2432 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2433 "TimeoutAction");
2434 return;
2435 }
2436
2437 crow::connections::systemBus->async_method_call(
2438 [aResp](const boost::system::error_code ec) {
2439 if (ec)
2440 {
2441 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2442 messages::internalError(aResp->res);
2443 return;
2444 }
2445 },
2446 "xyz.openbmc_project.Watchdog",
2447 "/xyz/openbmc_project/watchdog/host0",
2448 "org.freedesktop.DBus.Properties", "Set",
2449 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2450 std::variant<std::string>(wdtTimeOutActStr));
2451 }
2452
2453 if (wdtEnable)
2454 {
2455 crow::connections::systemBus->async_method_call(
2456 [aResp](const boost::system::error_code ec) {
2457 if (ec)
2458 {
2459 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2460 messages::internalError(aResp->res);
2461 return;
2462 }
2463 },
2464 "xyz.openbmc_project.Watchdog",
2465 "/xyz/openbmc_project/watchdog/host0",
2466 "org.freedesktop.DBus.Properties", "Set",
2467 "xyz.openbmc_project.State.Watchdog", "Enabled",
2468 std::variant<bool>(*wdtEnable));
2469 }
2470}
2471
Chris Cain37bbf982021-09-20 10:53:09 -05002472using ipsPropertiesType =
2473 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2474/**
2475 * @brief Parse the Idle Power Saver properties into json
2476 *
2477 * @param[in] aResp Shared pointer for completing asynchronous calls.
2478 * @param[in] properties IPS property data from DBus.
2479 *
2480 * @return true if successful
2481 */
2482bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2483 ipsPropertiesType& properties)
2484{
2485 for (const auto& property : properties)
2486 {
2487 if (property.first == "Enabled")
2488 {
2489 const bool* state = std::get_if<bool>(&property.second);
2490 if (!state)
2491 {
2492 return false;
2493 }
2494 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2495 }
2496 else if (property.first == "EnterUtilizationPercent")
2497 {
2498 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2499 if (!util)
2500 {
2501 return false;
2502 }
2503 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2504 }
2505 else if (property.first == "EnterDwellTime")
2506 {
2507 // Convert Dbus time from milliseconds to seconds
2508 const uint64_t* timeMilliseconds =
2509 std::get_if<uint64_t>(&property.second);
2510 if (!timeMilliseconds)
2511 {
2512 return false;
2513 }
2514 const std::chrono::duration<uint64_t, std::milli> ms(
2515 *timeMilliseconds);
2516 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2517 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2518 .count();
2519 }
2520 else if (property.first == "ExitUtilizationPercent")
2521 {
2522 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2523 if (!util)
2524 {
2525 return false;
2526 }
2527 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2528 }
2529 else if (property.first == "ExitDwellTime")
2530 {
2531 // Convert Dbus time from milliseconds to seconds
2532 const uint64_t* timeMilliseconds =
2533 std::get_if<uint64_t>(&property.second);
2534 if (!timeMilliseconds)
2535 {
2536 return false;
2537 }
2538 const std::chrono::duration<uint64_t, std::milli> ms(
2539 *timeMilliseconds);
2540 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2541 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2542 .count();
2543 }
2544 else
2545 {
2546 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2547 << property.first;
2548 }
2549 }
2550
2551 return true;
2552}
2553
2554/**
2555 * @brief Retrieves host watchdog timer properties over DBUS
2556 *
2557 * @param[in] aResp Shared pointer for completing asynchronous calls.
2558 *
2559 * @return None.
2560 */
2561inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2562{
2563 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2564
2565 // Get IdlePowerSaver object path:
2566 crow::connections::systemBus->async_method_call(
2567 [aResp](
2568 const boost::system::error_code ec,
2569 const std::vector<std::pair<
2570 std::string,
2571 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2572 subtree) {
2573 if (ec)
2574 {
2575 BMCWEB_LOG_DEBUG
2576 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2577 << ec;
2578 messages::internalError(aResp->res);
2579 return;
2580 }
2581 if (subtree.empty())
2582 {
2583 // This is an optional interface so just return
2584 // if there is no instance found
2585 BMCWEB_LOG_DEBUG << "No instances found";
2586 return;
2587 }
2588 if (subtree.size() > 1)
2589 {
2590 // More then one PowerIdlePowerSaver object is not supported and
2591 // is an error
2592 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2593 "Power.IdlePowerSaver objects: "
2594 << subtree.size();
2595 messages::internalError(aResp->res);
2596 return;
2597 }
2598 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2599 {
2600 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2601 messages::internalError(aResp->res);
2602 return;
2603 }
2604 const std::string& path = subtree[0].first;
2605 const std::string& service = subtree[0].second.begin()->first;
2606 if (service.empty())
2607 {
2608 BMCWEB_LOG_DEBUG
2609 << "Power.IdlePowerSaver service mapper error!";
2610 messages::internalError(aResp->res);
2611 return;
2612 }
2613
2614 // Valid IdlePowerSaver object found, now read the current values
2615 crow::connections::systemBus->async_method_call(
2616 [aResp](const boost::system::error_code ec,
2617 ipsPropertiesType& properties) {
2618 if (ec)
2619 {
2620 BMCWEB_LOG_ERROR
2621 << "DBUS response error on IdlePowerSaver GetAll: "
2622 << ec;
2623 messages::internalError(aResp->res);
2624 return;
2625 }
2626
2627 if (parseIpsProperties(aResp, properties) == false)
2628 {
2629 messages::internalError(aResp->res);
2630 return;
2631 }
2632 },
2633 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2634 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2635 },
2636 "xyz.openbmc_project.ObjectMapper",
2637 "/xyz/openbmc_project/object_mapper",
2638 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2639 std::array<const char*, 1>{
2640 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2641
2642 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2643}
2644
2645/**
2646 * @brief Sets Idle Power Saver properties.
2647 *
2648 * @param[in] aResp Shared pointer for generating response message.
2649 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2650 * RF request.
2651 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2652 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2653 * before entering idle state.
2654 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2655 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2656 * before exiting idle state
2657 *
2658 * @return None.
2659 */
2660inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2661 const std::optional<bool> ipsEnable,
2662 const std::optional<uint8_t> ipsEnterUtil,
2663 const std::optional<uint64_t> ipsEnterTime,
2664 const std::optional<uint8_t> ipsExitUtil,
2665 const std::optional<uint64_t> ipsExitTime)
2666{
2667 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2668
2669 // Get IdlePowerSaver object path:
2670 crow::connections::systemBus->async_method_call(
2671 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2672 ipsExitTime](
2673 const boost::system::error_code ec,
2674 const std::vector<std::pair<
2675 std::string,
2676 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2677 subtree) {
2678 if (ec)
2679 {
2680 BMCWEB_LOG_DEBUG
2681 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2682 << ec;
2683 messages::internalError(aResp->res);
2684 return;
2685 }
2686 if (subtree.empty())
2687 {
2688 // This is an optional D-Bus object, but user attempted to patch
2689 messages::resourceNotFound(aResp->res, "ComputerSystem",
2690 "IdlePowerSaver");
2691 return;
2692 }
2693 if (subtree.size() > 1)
2694 {
2695 // More then one PowerIdlePowerSaver object is not supported and
2696 // is an error
2697 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2698 "Power.IdlePowerSaver objects: "
2699 << subtree.size();
2700 messages::internalError(aResp->res);
2701 return;
2702 }
2703 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2704 {
2705 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2706 messages::internalError(aResp->res);
2707 return;
2708 }
2709 const std::string& path = subtree[0].first;
2710 const std::string& service = subtree[0].second.begin()->first;
2711 if (service.empty())
2712 {
2713 BMCWEB_LOG_DEBUG
2714 << "Power.IdlePowerSaver service mapper error!";
2715 messages::internalError(aResp->res);
2716 return;
2717 }
2718
2719 // Valid Power IdlePowerSaver object found, now set any values that
2720 // need to be updated
2721
2722 if (ipsEnable)
2723 {
2724 crow::connections::systemBus->async_method_call(
2725 [aResp](const boost::system::error_code ec) {
2726 if (ec)
2727 {
2728 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2729 messages::internalError(aResp->res);
2730 return;
2731 }
2732 },
2733 service, path, "org.freedesktop.DBus.Properties", "Set",
2734 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2735 "Enabled", std::variant<bool>(*ipsEnable));
2736 }
2737 if (ipsEnterUtil)
2738 {
2739 crow::connections::systemBus->async_method_call(
2740 [aResp](const boost::system::error_code ec) {
2741 if (ec)
2742 {
2743 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2744 messages::internalError(aResp->res);
2745 return;
2746 }
2747 },
2748 service, path, "org.freedesktop.DBus.Properties", "Set",
2749 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2750 "EnterUtilizationPercent",
2751 std::variant<uint8_t>(*ipsEnterUtil));
2752 }
2753 if (ipsEnterTime)
2754 {
2755 // Convert from seconds into milliseconds for DBus
2756 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2757 crow::connections::systemBus->async_method_call(
2758 [aResp](const boost::system::error_code ec) {
2759 if (ec)
2760 {
2761 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2762 messages::internalError(aResp->res);
2763 return;
2764 }
2765 },
2766 service, path, "org.freedesktop.DBus.Properties", "Set",
2767 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2768 "EnterDwellTime", std::variant<uint64_t>(timeMilliseconds));
2769 }
2770 if (ipsExitUtil)
2771 {
2772 crow::connections::systemBus->async_method_call(
2773 [aResp](const boost::system::error_code ec) {
2774 if (ec)
2775 {
2776 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2777 messages::internalError(aResp->res);
2778 return;
2779 }
2780 },
2781 service, path, "org.freedesktop.DBus.Properties", "Set",
2782 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2783 "ExitUtilizationPercent",
2784 std::variant<uint8_t>(*ipsExitUtil));
2785 }
2786 if (ipsExitTime)
2787 {
2788 // Convert from seconds into milliseconds for DBus
2789 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2790 crow::connections::systemBus->async_method_call(
2791 [aResp](const boost::system::error_code ec) {
2792 if (ec)
2793 {
2794 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2795 messages::internalError(aResp->res);
2796 return;
2797 }
2798 },
2799 service, path, "org.freedesktop.DBus.Properties", "Set",
2800 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2801 "ExitDwellTime", std::variant<uint64_t>(timeMilliseconds));
2802 }
2803 },
2804 "xyz.openbmc_project.ObjectMapper",
2805 "/xyz/openbmc_project/object_mapper",
2806 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2807 std::array<const char*, 1>{
2808 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2809
2810 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2811}
2812
Yong Lic45f0082019-10-10 14:19:01 +08002813/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002814 * SystemsCollection derived class for delivering ComputerSystems Collection
2815 * Schema
2816 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002817inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002818{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002820 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002821 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002822 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002823 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2824 asyncResp->res.jsonValue["@odata.type"] =
2825 "#ComputerSystemCollection.ComputerSystemCollection";
2826 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2827 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002828
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002829 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002830 [asyncResp](const boost::system::error_code ec,
2831 const std::variant<std::string>& /*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 {
2931 command = "xyz.openbmc_project.State.Host.Transition."
2932 "GracefulWarmReboot";
2933 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",
2977 std::variant<std::string>{command});
2978 }
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",
3005 std::variant<std::string>{command});
3006 }
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