blob: 2f88a7771f44917f952181468482810a46a4f2fa [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
George Liu0fda0f12021-11-16 10:06:17 +0800351 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800352 continue;
353 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500354 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800355 aResp->res.jsonValue
356 ["MemorySummary"]
357 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500358 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800359 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500360 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800361 if (preValue == nullptr)
362 {
363 continue;
364 }
George Liu0fda0f12021-11-16 10:06:17 +0800365 aResp->res.jsonValue
366 ["MemorySummary"]
367 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800368 *value / (1024 * 1024) +
369 *preValue;
370 aResp->res
371 .jsonValue["MemorySummary"]
372 ["Status"]["State"] =
373 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700374 }
Ed Tanous029573d2019-02-01 10:57:49 -0800375 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500376 else
377 {
378 auto getDimmProperties =
379 [aResp](
380 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000381 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500382 const std::variant<bool>&
383 dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000384 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500385 {
386 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800387 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000388 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500389 return;
390 }
391 updateDimmProperties(aResp,
392 dimmState);
393 };
394 crow::connections::systemBus
395 ->async_method_call(
396 std::move(getDimmProperties),
397 service, path,
George Liu0fda0f12021-11-16 10:06:17 +0800398 "org.freedesktop.DBus.Properties",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500399 "Get",
George Liu0fda0f12021-11-16 10:06:17 +0800400 "xyz.openbmc_project.State.Decorator.OperationalStatus",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500401 "Functional");
402 }
Ed Tanous029573d2019-02-01 10:57:49 -0800403 },
404 connection.first, path,
405 "org.freedesktop.DBus.Properties", "GetAll",
406 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700407
408 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800409 }
410 else if (interfaceName ==
411 "xyz.openbmc_project.Inventory.Item.Cpu")
412 {
413 BMCWEB_LOG_DEBUG
414 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500415
Ali Ahmed03fbed92021-09-03 02:33:43 -0500416 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700417
418 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800419 }
420 else if (interfaceName ==
421 "xyz.openbmc_project.Common.UUID")
422 {
423 BMCWEB_LOG_DEBUG
424 << "Found UUID, now get its properties.";
425 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500426 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000427 const boost::system::error_code ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500428 const std::vector<
429 std::pair<std::string, VariantType>>&
430 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000431 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800432 {
433 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000434 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800435 messages::internalError(aResp->res);
436 return;
437 }
438 BMCWEB_LOG_DEBUG << "Got "
439 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500440 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800441 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500442 VariantType>&
443 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800444 {
Ed Tanous029573d2019-02-01 10:57:49 -0800445 if (property.first == "UUID")
446 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500447 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500448 std::get_if<std::string>(
449 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700450
Ed Tanous029573d2019-02-01 10:57:49 -0800451 if (value != nullptr)
452 {
453 std::string valueStr = *value;
454 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700455 {
Ed Tanous029573d2019-02-01 10:57:49 -0800456 valueStr.insert(8, 1, '-');
457 valueStr.insert(13, 1, '-');
458 valueStr.insert(18, 1, '-');
459 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700460 }
Ed Tanous029573d2019-02-01 10:57:49 -0800461 BMCWEB_LOG_DEBUG << "UUID = "
462 << valueStr;
463 aResp->res.jsonValue["UUID"] =
464 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700465 }
466 }
Ed Tanous029573d2019-02-01 10:57:49 -0800467 }
468 },
469 connection.first, path,
470 "org.freedesktop.DBus.Properties", "GetAll",
471 "xyz.openbmc_project.Common.UUID");
472 }
473 else if (interfaceName ==
474 "xyz.openbmc_project.Inventory.Item.System")
475 {
476 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500477 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000478 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500479 const std::vector<
480 std::pair<std::string, VariantType>>&
481 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000482 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800483 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700484 // doesn't have to include this
485 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800486 return;
487 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500488 BMCWEB_LOG_DEBUG
489 << "Got " << propertiesList.size()
490 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800491 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500492 VariantType>&
493 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800494 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500495 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600496 property.first;
497 if ((propertyName == "PartNumber") ||
498 (propertyName == "SerialNumber") ||
499 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500500 (propertyName == "Model") ||
501 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800502 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500503 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600504 std::get_if<std::string>(
505 &property.second);
506 if (value != nullptr)
507 {
508 aResp->res
509 .jsonValue[propertyName] =
510 *value;
511 }
Ed Tanous029573d2019-02-01 10:57:49 -0800512 }
513 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500514
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600515 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500516 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600517 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500518 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800519 },
520 connection.first, path,
521 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800522 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700523
524 crow::connections::systemBus->async_method_call(
525 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000526 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500527 const std::variant<std::string>& property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000528 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700529 {
530 // doesn't have to include this
531 // interface
532 return;
533 }
534
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500535 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700536 std::get_if<std::string>(&property);
537 if (value != nullptr)
538 {
539 aResp->res.jsonValue["AssetTag"] =
540 *value;
541 }
542 },
543 connection.first, path,
544 "org.freedesktop.DBus.Properties", "Get",
George Liu0fda0f12021-11-16 10:06:17 +0800545 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
James Feiste4a4b9a2019-06-20 14:08:07 -0700546 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700547 }
548 }
549 }
550 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700551 },
552 "xyz.openbmc_project.ObjectMapper",
553 "/xyz/openbmc_project/object_mapper",
554 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700555 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500556 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700557 "xyz.openbmc_project.Inventory.Decorator.Asset",
558 "xyz.openbmc_project.Inventory.Item.Cpu",
559 "xyz.openbmc_project.Inventory.Item.Dimm",
560 "xyz.openbmc_project.Inventory.Item.System",
561 "xyz.openbmc_project.Common.UUID",
562 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700563}
564
565/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 * @brief Retrieves host state properties over dbus
567 *
568 * @param[in] aResp Shared pointer for completing asynchronous calls.
569 *
570 * @return None.
571 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800572inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700573{
574 BMCWEB_LOG_DEBUG << "Get host information.";
575 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800576 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500577 const std::variant<std::string>& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700578 if (ec)
579 {
580 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700581 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700582 return;
583 }
Ed Tanous66173382018-08-15 18:20:59 -0700584
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500585 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700586 BMCWEB_LOG_DEBUG << "Host state: " << *s;
587 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700588 {
Ed Tanous66173382018-08-15 18:20:59 -0700589 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800590 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700591 {
Ed Tanous66173382018-08-15 18:20:59 -0700592 aResp->res.jsonValue["PowerState"] = "On";
593 aResp->res.jsonValue["Status"]["State"] = "Enabled";
594 }
George Liu0fda0f12021-11-16 10:06:17 +0800595 else if (*s ==
596 "xyz.openbmc_project.State.Host.HostState.Quiesced")
Gunnar Mills8c888602020-05-01 14:25:09 -0500597 {
598 aResp->res.jsonValue["PowerState"] = "On";
599 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
600 }
George Liu0fda0f12021-11-16 10:06:17 +0800601 else if (
602 *s ==
603 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
Andrew Geissler83935af2020-02-13 10:24:53 -0600604 {
605 aResp->res.jsonValue["PowerState"] = "On";
606 aResp->res.jsonValue["Status"]["State"] = "InTest";
607 }
George Liu0fda0f12021-11-16 10:06:17 +0800608 else if (
609 *s ==
610 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600611 {
612 aResp->res.jsonValue["PowerState"] = "PoweringOn";
Noah Brewer15c27bf2021-04-27 15:24:25 -0500613 aResp->res.jsonValue["Status"]["State"] = "Starting";
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600614 }
George Liu0fda0f12021-11-16 10:06:17 +0800615 else if (
616 *s ==
617 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600618 {
619 aResp->res.jsonValue["PowerState"] = "PoweringOff";
620 aResp->res.jsonValue["Status"]["State"] = "Disabled";
621 }
Ed Tanous66173382018-08-15 18:20:59 -0700622 else
623 {
624 aResp->res.jsonValue["PowerState"] = "Off";
625 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700626 }
627 }
628 },
629 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700630 "org.freedesktop.DBus.Properties", "Get",
631 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700632}
633
634/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500635 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530636 *
637 * @param[in] dbusSource The boot source in DBUS speak.
638 *
639 * @return Returns as a string, the boot source in Redfish terms. If translation
640 * cannot be done, returns an empty string.
641 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000642inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530643{
644 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
645 {
646 return "None";
647 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700648 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530649 {
650 return "Hdd";
651 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700652 if (dbusSource ==
653 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530654 {
655 return "Cd";
656 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700657 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530658 {
659 return "Pxe";
660 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700661 if (dbusSource ==
662 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700663 {
664 return "Usb";
665 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700666 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530667}
668
669/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300670 * @brief Translates boot type DBUS property value to redfish.
671 *
672 * @param[in] dbusType The boot type in DBUS speak.
673 *
674 * @return Returns as a string, the boot type in Redfish terms. If translation
675 * cannot be done, returns an empty string.
676 */
677inline std::string dbusToRfBootType(const std::string& dbusType)
678{
679 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
680 {
681 return "Legacy";
682 }
683 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
684 {
685 return "UEFI";
686 }
687 return "";
688}
689
690/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500691 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530692 *
693 * @param[in] dbusMode The boot mode in DBUS speak.
694 *
695 * @return Returns as a string, the boot mode in Redfish terms. If translation
696 * cannot be done, returns an empty string.
697 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000698inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530699{
700 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
701 {
702 return "None";
703 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700704 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530705 {
706 return "Diags";
707 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700708 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530709 {
710 return "BiosSetup";
711 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700712 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530713}
714
715/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500716 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530717 *
718 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700719 * @param[out] bootSource The DBus source
720 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530721 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700722 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530723 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800724inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500725 const std::string& rfSource,
726 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530727{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300728 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
729 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700730
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 if (rfSource == "None")
732 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700733 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530734 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700735 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530736 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700737 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
738 }
739 else if (rfSource == "Hdd")
740 {
741 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
742 }
743 else if (rfSource == "Diags")
744 {
745 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
746 }
747 else if (rfSource == "Cd")
748 {
749 bootSource =
750 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
751 }
752 else if (rfSource == "BiosSetup")
753 {
754 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530755 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700756 else if (rfSource == "Usb")
757 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700758 bootSource =
759 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700760 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530761 else
762 {
George Liu0fda0f12021-11-16 10:06:17 +0800763 BMCWEB_LOG_DEBUG
764 << "Invalid property value for BootSourceOverrideTarget: "
765 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 messages::propertyValueNotInList(aResp->res, rfSource,
767 "BootSourceTargetOverride");
768 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530769 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700770 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530771}
Ali Ahmed19817712021-06-29 17:01:52 -0500772
Andrew Geissler978b8802020-11-19 13:36:40 -0600773/**
774 * @brief Retrieves boot progress of the system
775 *
776 * @param[in] aResp Shared pointer for generating response message.
777 *
778 * @return None.
779 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800780inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600781{
782 crow::connections::systemBus->async_method_call(
783 [aResp](const boost::system::error_code ec,
784 const std::variant<std::string>& bootProgress) {
785 if (ec)
786 {
787 // BootProgress is an optional object so just do nothing if
788 // not found
789 return;
790 }
791
792 const std::string* bootProgressStr =
793 std::get_if<std::string>(&bootProgress);
794
795 if (!bootProgressStr)
796 {
797 // Interface implemented but property not found, return error
798 // for that
799 messages::internalError(aResp->res);
800 return;
801 }
802
803 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
804
805 // Now convert the D-Bus BootProgress to the appropriate Redfish
806 // enum
807 std::string rfBpLastState = "None";
George Liu0fda0f12021-11-16 10:06:17 +0800808 if (*bootProgressStr ==
809 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified")
Andrew Geissler978b8802020-11-19 13:36:40 -0600810 {
811 rfBpLastState = "None";
812 }
George Liu0fda0f12021-11-16 10:06:17 +0800813 else if (
814 *bootProgressStr ==
815 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.PrimaryProcInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600816 {
817 rfBpLastState = "PrimaryProcessorInitializationStarted";
818 }
George Liu0fda0f12021-11-16 10:06:17 +0800819 else if (
820 *bootProgressStr ==
821 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.BusInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600822 {
823 rfBpLastState = "BusInitializationStarted";
824 }
George Liu0fda0f12021-11-16 10:06:17 +0800825 else if (
826 *bootProgressStr ==
827 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.MemoryInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600828 {
829 rfBpLastState = "MemoryInitializationStarted";
830 }
George Liu0fda0f12021-11-16 10:06:17 +0800831 else if (
832 *bootProgressStr ==
833 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.SecondaryProcInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600834 {
835 rfBpLastState = "SecondaryProcessorInitializationStarted";
836 }
George Liu0fda0f12021-11-16 10:06:17 +0800837 else if (
838 *bootProgressStr ==
839 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.PCIInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600840 {
841 rfBpLastState = "PCIResourceConfigStarted";
842 }
George Liu0fda0f12021-11-16 10:06:17 +0800843 else if (
844 *bootProgressStr ==
845 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.SystemInitComplete")
Andrew Geissler978b8802020-11-19 13:36:40 -0600846 {
847 rfBpLastState = "SystemHardwareInitializationComplete";
848 }
George Liu0fda0f12021-11-16 10:06:17 +0800849 else if (
850 *bootProgressStr ==
851 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSStart")
Andrew Geissler978b8802020-11-19 13:36:40 -0600852 {
853 rfBpLastState = "OSBootStarted";
854 }
George Liu0fda0f12021-11-16 10:06:17 +0800855 else if (
856 *bootProgressStr ==
857 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSRunning")
Andrew Geissler978b8802020-11-19 13:36:40 -0600858 {
859 rfBpLastState = "OSRunning";
860 }
861 else
862 {
863 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
864 << *bootProgressStr;
865 // Just return the default
866 }
867
868 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
869 },
870 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
871 "org.freedesktop.DBus.Properties", "Get",
872 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
873}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530874
875/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300876 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300877 *
878 * @param[in] aResp Shared pointer for generating response message.
879 *
880 * @return None.
881 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300883inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300884{
885 crow::connections::systemBus->async_method_call(
886 [aResp](const boost::system::error_code ec,
887 const std::variant<std::string>& bootType) {
888 if (ec)
889 {
890 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300891 return;
892 }
893
894 const std::string* bootTypeStr =
895 std::get_if<std::string>(&bootType);
896
897 if (!bootTypeStr)
898 {
899 messages::internalError(aResp->res);
900 return;
901 }
902
903 BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
904
George Liu0fda0f12021-11-16 10:06:17 +0800905 aResp->res
906 .jsonValue["Boot"]
907 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
908 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300909
910 auto rfType = dbusToRfBootType(*bootTypeStr);
911 if (rfType.empty())
912 {
913 messages::internalError(aResp->res);
914 return;
915 }
916
917 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300919 "xyz.openbmc_project.Settings",
920 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300921 "org.freedesktop.DBus.Properties", "Get",
922 "xyz.openbmc_project.Control.Boot.Type", "BootType");
923}
924
925/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300926 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530927 *
928 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530929 *
930 * @return None.
931 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300932
933inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530934{
935 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300936 [aResp](const boost::system::error_code ec,
937 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938 if (ec)
939 {
940 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
941 messages::internalError(aResp->res);
942 return;
943 }
944
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500945 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530946 std::get_if<std::string>(&bootMode);
947
948 if (!bootModeStr)
949 {
950 messages::internalError(aResp->res);
951 return;
952 }
953
954 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
955
George Liu0fda0f12021-11-16 10:06:17 +0800956 aResp->res
957 .jsonValue["Boot"]
958 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
959 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530960
961 if (*bootModeStr !=
962 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
963 {
964 auto rfMode = dbusToRfBootMode(*bootModeStr);
965 if (!rfMode.empty())
966 {
967 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
968 rfMode;
969 }
970 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530971 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300972 "xyz.openbmc_project.Settings",
973 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 "org.freedesktop.DBus.Properties", "Get",
975 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
976}
977
978/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300979 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530980 *
981 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530982 *
983 * @return None.
984 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300985
986inline void
987 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530988{
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530989 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300990 [aResp](const boost::system::error_code ec,
991 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530992 if (ec)
993 {
994 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
995 messages::internalError(aResp->res);
996 return;
997 }
998
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500999 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000 std::get_if<std::string>(&bootSource);
1001
1002 if (!bootSourceStr)
1003 {
1004 messages::internalError(aResp->res);
1005 return;
1006 }
1007 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1008
1009 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1010 if (!rfSource.empty())
1011 {
1012 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1013 rfSource;
1014 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001015
1016 // Get BootMode as BootSourceOverrideTarget is constructed
1017 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001018 getBootOverrideMode(aResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001020 "xyz.openbmc_project.Settings",
1021 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022 "org.freedesktop.DBus.Properties", "Get",
1023 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301024}
1025
1026/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001027 * @brief This functions abstracts all the logic behind getting a
1028 * "BootSourceOverrideEnabled" property from an overall boot override enable
1029 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301030 *
1031 * @param[in] aResp Shared pointer for generating response message.
1032 *
1033 * @return None.
1034 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301035
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001036inline void
1037 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1038 const bool bootOverrideEnableSetting)
1039{
1040 if (!bootOverrideEnableSetting)
1041 {
1042 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1043 return;
1044 }
1045
1046 // If boot source override is enabled, we need to check 'one_time'
1047 // property to set a correct value for the "BootSourceOverrideEnabled"
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301048 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001049 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001050 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301051 if (ec)
1052 {
1053 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001054 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301055 return;
1056 }
1057
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001058 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301059
1060 if (!oneTimePtr)
1061 {
1062 messages::internalError(aResp->res);
1063 return;
1064 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001065
1066 bool oneTimeSetting = *oneTimePtr;
1067
1068 if (oneTimeSetting)
1069 {
1070 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1071 "Once";
1072 }
1073 else
1074 {
1075 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1076 "Continuous";
1077 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301078 },
1079 "xyz.openbmc_project.Settings",
1080 "/xyz/openbmc_project/control/host0/boot/one_time",
1081 "org.freedesktop.DBus.Properties", "Get",
1082 "xyz.openbmc_project.Object.Enable", "Enabled");
1083}
1084
1085/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001086 * @brief Retrieves boot override enable over DBUS
1087 *
1088 * @param[in] aResp Shared pointer for generating response message.
1089 *
1090 * @return None.
1091 */
1092
1093inline void
1094 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1095{
1096 crow::connections::systemBus->async_method_call(
1097 [aResp](const boost::system::error_code ec,
1098 const std::variant<bool>& bootOverrideEnable) {
1099 if (ec)
1100 {
1101 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1102 messages::internalError(aResp->res);
1103 return;
1104 }
1105
1106 const bool* bootOverrideEnablePtr =
1107 std::get_if<bool>(&bootOverrideEnable);
1108
1109 if (!bootOverrideEnablePtr)
1110 {
1111 messages::internalError(aResp->res);
1112 return;
1113 }
1114
1115 processBootOverrideEnable(aResp, *bootOverrideEnablePtr);
1116 },
1117 "xyz.openbmc_project.Settings",
1118 "/xyz/openbmc_project/control/host0/boot",
1119 "org.freedesktop.DBus.Properties", "Get",
1120 "xyz.openbmc_project.Object.Enable", "Enabled");
1121}
1122
1123/**
1124 * @brief Retrieves boot source override properties
1125 *
1126 * @param[in] aResp Shared pointer for generating response message.
1127 *
1128 * @return None.
1129 */
1130inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1131{
1132 BMCWEB_LOG_DEBUG << "Get boot information.";
1133
1134 getBootOverrideSource(aResp);
1135 getBootOverrideType(aResp);
1136 getBootOverrideEnable(aResp);
1137}
1138
1139/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001140 * @brief Retrieves the Last Reset Time
1141 *
1142 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1143 * and power off. Even though this is the "system" Redfish object look at the
1144 * chassis D-Bus interface for the LastStateChangeTime since this has the
1145 * last power operation time.
1146 *
1147 * @param[in] aResp Shared pointer for generating response message.
1148 *
1149 * @return None.
1150 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001151inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001152{
1153 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1154
1155 crow::connections::systemBus->async_method_call(
1156 [aResp](const boost::system::error_code ec,
1157 std::variant<uint64_t>& lastResetTime) {
1158 if (ec)
1159 {
1160 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1161 return;
1162 }
1163
1164 const uint64_t* lastResetTimePtr =
1165 std::get_if<uint64_t>(&lastResetTime);
1166
1167 if (!lastResetTimePtr)
1168 {
1169 messages::internalError(aResp->res);
1170 return;
1171 }
1172 // LastStateChangeTime is epoch time, in milliseconds
1173 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1174 time_t lastResetTimeStamp =
1175 static_cast<time_t>(*lastResetTimePtr / 1000);
1176
1177 // Convert to ISO 8601 standard
1178 aResp->res.jsonValue["LastResetTime"] =
1179 crow::utility::getDateTime(lastResetTimeStamp);
1180 },
1181 "xyz.openbmc_project.State.Chassis",
1182 "/xyz/openbmc_project/state/chassis0",
1183 "org.freedesktop.DBus.Properties", "Get",
1184 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1185}
1186
1187/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001188 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1189 *
1190 * @param[in] aResp Shared pointer for generating response message.
1191 *
1192 * @return None.
1193 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001194inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001195{
1196 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1197
1198 crow::connections::systemBus->async_method_call(
1199 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001200 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001201 if (ec)
1202 {
1203 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1204 return;
1205 }
1206
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001207 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001208 std::get_if<bool>(&autoRebootEnabled);
1209
1210 if (!autoRebootEnabledPtr)
1211 {
1212 messages::internalError(aResp->res);
1213 return;
1214 }
1215
1216 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1217 if (*autoRebootEnabledPtr == true)
1218 {
1219 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1220 "RetryAttempts";
1221 // If AutomaticRetry (AutoReboot) is enabled see how many
1222 // attempts are left
1223 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001224 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001225 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001226 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001227 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001228 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001229 return;
1230 }
1231
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001232 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001233 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1234
1235 if (!autoRebootAttemptsLeftPtr)
1236 {
1237 messages::internalError(aResp->res);
1238 return;
1239 }
1240
1241 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1242 << *autoRebootAttemptsLeftPtr;
1243
1244 aResp->res
1245 .jsonValue["Boot"]
1246 ["RemainingAutomaticRetryAttempts"] =
1247 *autoRebootAttemptsLeftPtr;
1248 },
1249 "xyz.openbmc_project.State.Host",
1250 "/xyz/openbmc_project/state/host0",
1251 "org.freedesktop.DBus.Properties", "Get",
1252 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1253 "AttemptsLeft");
1254 }
1255 else
1256 {
1257 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1258 "Disabled";
1259 }
1260
1261 // Not on D-Bus. Hardcoded here:
1262 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1263 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001264
1265 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1266 // and RetryAttempts. OpenBMC only supports Disabled and
1267 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001268 aResp->res
1269 .jsonValue["Boot"]
1270 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1271 "Disabled", "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001272 },
1273 "xyz.openbmc_project.Settings",
1274 "/xyz/openbmc_project/control/host0/auto_reboot",
1275 "org.freedesktop.DBus.Properties", "Get",
1276 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1277}
1278
1279/**
George Liuc6a620f2020-04-10 17:18:11 +08001280 * @brief Retrieves power restore policy over DBUS.
1281 *
1282 * @param[in] aResp Shared pointer for generating response message.
1283 *
1284 * @return None.
1285 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001286inline void
1287 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001288{
1289 BMCWEB_LOG_DEBUG << "Get power restore policy";
1290
1291 crow::connections::systemBus->async_method_call(
1292 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001293 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001294 if (ec)
1295 {
1296 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1297 return;
1298 }
1299
George Liu0fda0f12021-11-16 10:06:17 +08001300 const boost::container::flat_map<std::string, std::string> policyMaps = {
1301 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1302 "AlwaysOn"},
1303 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1304 "AlwaysOff"},
1305 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1306 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001307
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001308 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001309
1310 if (!policyPtr)
1311 {
1312 messages::internalError(aResp->res);
1313 return;
1314 }
1315
1316 auto policyMapsIt = policyMaps.find(*policyPtr);
1317 if (policyMapsIt == policyMaps.end())
1318 {
1319 messages::internalError(aResp->res);
1320 return;
1321 }
1322
1323 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1324 },
1325 "xyz.openbmc_project.Settings",
1326 "/xyz/openbmc_project/control/host0/power_restore_policy",
1327 "org.freedesktop.DBus.Properties", "Get",
1328 "xyz.openbmc_project.Control.Power.RestorePolicy",
1329 "PowerRestorePolicy");
1330}
1331
1332/**
Ali Ahmed19817712021-06-29 17:01:52 -05001333 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1334 * TPM is required for booting the host.
1335 *
1336 * @param[in] aResp Shared pointer for generating response message.
1337 *
1338 * @return None.
1339 */
1340inline void getTrustedModuleRequiredToBoot(
1341 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1342{
1343 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1344
1345 crow::connections::systemBus->async_method_call(
1346 [aResp](
1347 const boost::system::error_code ec,
1348 std::vector<std::pair<
1349 std::string,
1350 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1351 subtree) {
1352 if (ec)
1353 {
1354 BMCWEB_LOG_DEBUG
1355 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1356 // This is an optional D-Bus object so just return if
1357 // error occurs
1358 return;
1359 }
1360 if (subtree.size() == 0)
1361 {
1362 // As noted above, this is an optional interface so just return
1363 // if there is no instance found
1364 return;
1365 }
1366
1367 /* When there is more than one TPMEnable object... */
1368 if (subtree.size() > 1)
1369 {
1370 BMCWEB_LOG_DEBUG
1371 << "DBUS response has more than 1 TPM Enable object:"
1372 << subtree.size();
1373 // Throw an internal Error and return
1374 messages::internalError(aResp->res);
1375 return;
1376 }
1377
1378 // Make sure the Dbus response map has a service and objectPath
1379 // field
1380 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1381 {
1382 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1383 messages::internalError(aResp->res);
1384 return;
1385 }
1386
1387 const std::string& path = subtree[0].first;
1388 const std::string& serv = subtree[0].second.begin()->first;
1389
1390 // Valid TPM Enable object found, now reading the current value
1391 crow::connections::systemBus->async_method_call(
1392 [aResp](const boost::system::error_code ec,
1393 std::variant<bool>& tpmRequired) {
1394 if (ec)
1395 {
1396 BMCWEB_LOG_DEBUG
1397 << "D-BUS response error on TPM.Policy Get" << ec;
1398 messages::internalError(aResp->res);
1399 return;
1400 }
1401
1402 const bool* tpmRequiredVal =
1403 std::get_if<bool>(&tpmRequired);
1404
1405 if (!tpmRequiredVal)
1406 {
1407 messages::internalError(aResp->res);
1408 return;
1409 }
1410
1411 if (*tpmRequiredVal == true)
1412 {
1413 aResp->res
1414 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1415 "Required";
1416 }
1417 else
1418 {
1419 aResp->res
1420 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1421 "Disabled";
1422 }
1423 },
1424 serv, path, "org.freedesktop.DBus.Properties", "Get",
1425 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1426 },
1427 "xyz.openbmc_project.ObjectMapper",
1428 "/xyz/openbmc_project/object_mapper",
1429 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1430 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1431}
1432
1433/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001434 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1435 * TPM is required for booting the host.
1436 *
1437 * @param[in] aResp Shared pointer for generating response message.
1438 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1439 *
1440 * @return None.
1441 */
1442inline void setTrustedModuleRequiredToBoot(
1443 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1444{
1445 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1446
1447 crow::connections::systemBus->async_method_call(
1448 [aResp, tpmRequired](
1449 const boost::system::error_code ec,
1450 std::vector<std::pair<
1451 std::string,
1452 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1453 subtree) {
1454 if (ec)
1455 {
1456 BMCWEB_LOG_DEBUG
1457 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1458 messages::internalError(aResp->res);
1459 return;
1460 }
1461 if (subtree.size() == 0)
1462 {
1463 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1464 "TrustedModuleRequiredToBoot");
1465 return;
1466 }
1467
1468 /* When there is more than one TPMEnable object... */
1469 if (subtree.size() > 1)
1470 {
1471 BMCWEB_LOG_DEBUG
1472 << "DBUS response has more than 1 TPM Enable object:"
1473 << subtree.size();
1474 // Throw an internal Error and return
1475 messages::internalError(aResp->res);
1476 return;
1477 }
1478
1479 // Make sure the Dbus response map has a service and objectPath
1480 // field
1481 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1482 {
1483 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1484 messages::internalError(aResp->res);
1485 return;
1486 }
1487
1488 const std::string& path = subtree[0].first;
1489 const std::string& serv = subtree[0].second.begin()->first;
1490
1491 if (serv.empty())
1492 {
1493 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1494 messages::internalError(aResp->res);
1495 return;
1496 }
1497
1498 // Valid TPM Enable object found, now setting the value
1499 crow::connections::systemBus->async_method_call(
1500 [aResp](const boost::system::error_code ec) {
1501 if (ec)
1502 {
George Liu0fda0f12021-11-16 10:06:17 +08001503 BMCWEB_LOG_DEBUG
1504 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1505 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001506 messages::internalError(aResp->res);
1507 return;
1508 }
1509 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1510 },
1511 serv, path, "org.freedesktop.DBus.Properties", "Set",
1512 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1513 std::variant<bool>(tpmRequired));
1514 },
1515 "xyz.openbmc_project.ObjectMapper",
1516 "/xyz/openbmc_project/object_mapper",
1517 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1518 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1519}
1520
1521/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301522 * @brief Sets boot properties into DBUS object(s).
1523 *
1524 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001525 * @param[in] bootType The boot type to set.
1526 * @return Integer error code.
1527 */
1528inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001529 const std::optional<std::string>& bootType)
1530{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001531 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001532
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001533 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001534 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001535 return;
1536 }
1537
1538 // Source target specified
1539 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1540 // Figure out which DBUS interface and property to use
1541 if (*bootType == "Legacy")
1542 {
1543 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1544 }
1545 else if (*bootType == "UEFI")
1546 {
1547 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1548 }
1549 else
1550 {
1551 BMCWEB_LOG_DEBUG << "Invalid property value for "
1552 "BootSourceOverrideMode: "
1553 << *bootType;
1554 messages::propertyValueNotInList(aResp->res, *bootType,
1555 "BootSourceOverrideMode");
1556 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001557 }
1558
1559 // Act on validated parameters
1560 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1561
1562 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001563 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001564 if (ec)
1565 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001566 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1567 if (ec.value() == boost::asio::error::host_unreachable)
1568 {
1569 messages::resourceNotFound(aResp->res, "Set", "BootType");
1570 return;
1571 }
1572 messages::internalError(aResp->res);
1573 return;
1574 }
1575 BMCWEB_LOG_DEBUG << "Boot type update done.";
1576 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001577 "xyz.openbmc_project.Settings",
1578 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001579 "org.freedesktop.DBus.Properties", "Set",
1580 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1581 std::variant<std::string>(bootTypeStr));
1582}
1583
1584/**
1585 * @brief Sets boot properties into DBUS object(s).
1586 *
1587 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001588 * @param[in] bootType The boot type to set.
1589 * @return Integer error code.
1590 */
1591inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1592 const std::optional<std::string>& bootEnable)
1593{
1594 if (!bootEnable)
1595 {
1596 return;
1597 }
1598 // Source target specified
1599 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1600
1601 bool bootOverrideEnable = false;
1602 bool bootOverridePersistent = false;
1603 // Figure out which DBUS interface and property to use
1604 if (*bootEnable == "Disabled")
1605 {
1606 bootOverrideEnable = false;
1607 }
1608 else if (*bootEnable == "Once")
1609 {
1610 bootOverrideEnable = true;
1611 bootOverridePersistent = false;
1612 }
1613 else if (*bootEnable == "Continuous")
1614 {
1615 bootOverrideEnable = true;
1616 bootOverridePersistent = true;
1617 }
1618 else
1619 {
George Liu0fda0f12021-11-16 10:06:17 +08001620 BMCWEB_LOG_DEBUG
1621 << "Invalid property value for BootSourceOverrideEnabled: "
1622 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001623 messages::propertyValueNotInList(aResp->res, *bootEnable,
1624 "BootSourceOverrideEnabled");
1625 return;
1626 }
1627
1628 // Act on validated parameters
1629 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1630
1631 crow::connections::systemBus->async_method_call(
1632 [aResp](const boost::system::error_code ec) {
1633 if (ec)
1634 {
1635 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1636 messages::internalError(aResp->res);
1637 return;
1638 }
1639 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1640 },
1641 "xyz.openbmc_project.Settings",
1642 "/xyz/openbmc_project/control/host0/boot",
1643 "org.freedesktop.DBus.Properties", "Set",
1644 "xyz.openbmc_project.Object.Enable", "Enabled",
1645 std::variant<bool>(bootOverrideEnable));
1646
1647 if (!bootOverrideEnable)
1648 {
1649 return;
1650 }
1651
1652 // In case boot override is enabled we need to set correct value for the
1653 // 'one_time' enable DBus interface
1654 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1655 << bootOverridePersistent;
1656
1657 crow::connections::systemBus->async_method_call(
1658 [aResp](const boost::system::error_code ec) {
1659 if (ec)
1660 {
1661 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1662 messages::internalError(aResp->res);
1663 return;
1664 }
1665 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1666 },
1667 "xyz.openbmc_project.Settings",
1668 "/xyz/openbmc_project/control/host0/boot/one_time",
1669 "org.freedesktop.DBus.Properties", "Set",
1670 "xyz.openbmc_project.Object.Enable", "Enabled",
1671 std::variant<bool>(!bootOverridePersistent));
1672}
1673
1674/**
1675 * @brief Sets boot properties into DBUS object(s).
1676 *
1677 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301678 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301679 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001680 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301681 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001682inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001683 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301684{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001685 std::string bootSourceStr;
1686 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001687
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001688 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301689 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690 return;
1691 }
1692
1693 // Source target specified
1694 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1695 // Figure out which DBUS interface and property to use
1696 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1697 {
1698 BMCWEB_LOG_DEBUG
1699 << "Invalid property value for BootSourceOverrideTarget: "
1700 << *bootSource;
1701 messages::propertyValueNotInList(aResp->res, *bootSource,
1702 "BootSourceTargetOverride");
1703 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001704 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301705
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001706 // Act on validated parameters
1707 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1708 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001709
1710 crow::connections::systemBus->async_method_call(
1711 [aResp](const boost::system::error_code ec) {
1712 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301713 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001714 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1715 messages::internalError(aResp->res);
1716 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301717 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001718 BMCWEB_LOG_DEBUG << "Boot source update done.";
1719 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001720 "xyz.openbmc_project.Settings",
1721 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001722 "org.freedesktop.DBus.Properties", "Set",
1723 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1724 std::variant<std::string>(bootSourceStr));
1725
1726 crow::connections::systemBus->async_method_call(
1727 [aResp](const boost::system::error_code ec) {
1728 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301729 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001730 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1731 messages::internalError(aResp->res);
1732 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301733 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001734 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1735 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001736 "xyz.openbmc_project.Settings",
1737 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001738 "org.freedesktop.DBus.Properties", "Set",
1739 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1740 std::variant<std::string>(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001741}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001742
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001743/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001744 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301745 *
1746 * @param[in] aResp Shared pointer for generating response message.
1747 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001748 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301749 * @param[in] bootEnable The boot override enable from incoming RF request.
1750 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001751 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301752 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001753
1754inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1755 const std::optional<std::string>& bootSource,
1756 const std::optional<std::string>& bootType,
1757 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301758{
1759 BMCWEB_LOG_DEBUG << "Set boot information.";
1760
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001761 setBootModeOrSource(aResp, bootSource);
1762 setBootType(aResp, bootType);
1763 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301764}
1765
George Liuc6a620f2020-04-10 17:18:11 +08001766/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001767 * @brief Sets AssetTag
1768 *
1769 * @param[in] aResp Shared pointer for generating response message.
1770 * @param[in] assetTag "AssetTag" from request.
1771 *
1772 * @return None.
1773 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001774inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001775 const std::string& assetTag)
1776{
1777 crow::connections::systemBus->async_method_call(
1778 [aResp, assetTag](
1779 const boost::system::error_code ec,
1780 const std::vector<std::pair<
1781 std::string,
1782 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1783 subtree) {
1784 if (ec)
1785 {
1786 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1787 messages::internalError(aResp->res);
1788 return;
1789 }
1790 if (subtree.size() == 0)
1791 {
1792 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1793 messages::internalError(aResp->res);
1794 return;
1795 }
1796 // Assume only 1 system D-Bus object
1797 // Throw an error if there is more than 1
1798 if (subtree.size() > 1)
1799 {
1800 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1801 messages::internalError(aResp->res);
1802 return;
1803 }
1804 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1805 {
1806 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1807 messages::internalError(aResp->res);
1808 return;
1809 }
1810
1811 const std::string& path = subtree[0].first;
1812 const std::string& service = subtree[0].second.begin()->first;
1813
1814 if (service.empty())
1815 {
1816 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1817 messages::internalError(aResp->res);
1818 return;
1819 }
1820
1821 crow::connections::systemBus->async_method_call(
1822 [aResp](const boost::system::error_code ec2) {
1823 if (ec2)
1824 {
1825 BMCWEB_LOG_DEBUG
1826 << "D-Bus response error on AssetTag Set " << ec2;
1827 messages::internalError(aResp->res);
1828 return;
1829 }
1830 },
1831 service, path, "org.freedesktop.DBus.Properties", "Set",
1832 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1833 std::variant<std::string>(assetTag));
1834 },
1835 "xyz.openbmc_project.ObjectMapper",
1836 "/xyz/openbmc_project/object_mapper",
1837 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1838 "/xyz/openbmc_project/inventory", int32_t(0),
1839 std::array<const char*, 1>{
1840 "xyz.openbmc_project.Inventory.Item.System"});
1841}
1842
1843/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001844 * @brief Sets automaticRetry (Auto Reboot)
1845 *
1846 * @param[in] aResp Shared pointer for generating response message.
1847 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1848 *
1849 * @return None.
1850 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001851inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001852 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001853{
1854 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1855
1856 // OpenBMC only supports "Disabled" and "RetryAttempts".
1857 bool autoRebootEnabled;
1858
1859 if (automaticRetryConfig == "Disabled")
1860 {
1861 autoRebootEnabled = false;
1862 }
1863 else if (automaticRetryConfig == "RetryAttempts")
1864 {
1865 autoRebootEnabled = true;
1866 }
1867 else
1868 {
George Liu0fda0f12021-11-16 10:06:17 +08001869 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001870 << automaticRetryConfig;
1871 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1872 "AutomaticRetryConfig");
1873 return;
1874 }
1875
1876 crow::connections::systemBus->async_method_call(
1877 [aResp](const boost::system::error_code ec) {
1878 if (ec)
1879 {
1880 messages::internalError(aResp->res);
1881 return;
1882 }
1883 },
1884 "xyz.openbmc_project.Settings",
1885 "/xyz/openbmc_project/control/host0/auto_reboot",
1886 "org.freedesktop.DBus.Properties", "Set",
1887 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1888 std::variant<bool>(autoRebootEnabled));
1889}
1890
1891/**
George Liuc6a620f2020-04-10 17:18:11 +08001892 * @brief Sets power restore policy properties.
1893 *
1894 * @param[in] aResp Shared pointer for generating response message.
1895 * @param[in] policy power restore policy properties from request.
1896 *
1897 * @return None.
1898 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001899inline void
1900 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1901 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001902{
1903 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1904
1905 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001906 {"AlwaysOn",
1907 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1908 {"AlwaysOff",
1909 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1910 {"LastState",
1911 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001912
1913 std::string powerRestorPolicy;
1914
Gunnar Mills4e69c902021-01-05 19:50:11 -06001915 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001916 if (policyMapsIt == policyMaps.end())
1917 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001918 messages::propertyValueNotInList(aResp->res, policy,
1919 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001920 return;
1921 }
1922
1923 powerRestorPolicy = policyMapsIt->second;
1924
1925 crow::connections::systemBus->async_method_call(
1926 [aResp](const boost::system::error_code ec) {
1927 if (ec)
1928 {
1929 messages::internalError(aResp->res);
1930 return;
1931 }
1932 },
1933 "xyz.openbmc_project.Settings",
1934 "/xyz/openbmc_project/control/host0/power_restore_policy",
1935 "org.freedesktop.DBus.Properties", "Set",
1936 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1937 std::variant<std::string>(powerRestorPolicy));
1938}
1939
AppaRao Pulia6349912019-10-18 17:16:08 +05301940#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1941/**
1942 * @brief Retrieves provisioning status
1943 *
1944 * @param[in] aResp Shared pointer for completing asynchronous calls.
1945 *
1946 * @return None.
1947 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001948inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301949{
1950 BMCWEB_LOG_DEBUG << "Get OEM information.";
1951 crow::connections::systemBus->async_method_call(
1952 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001953 const std::vector<std::pair<std::string, VariantType>>&
1954 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301955 nlohmann::json& oemPFR =
1956 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001957 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1958 "#OemComputerSystem.OpenBmc";
1959 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1960
AppaRao Pulia6349912019-10-18 17:16:08 +05301961 if (ec)
1962 {
1963 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301964 // not an error, don't have to have the interface
1965 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301966 return;
1967 }
1968
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001969 const bool* provState = nullptr;
1970 const bool* lockState = nullptr;
1971 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301972 propertiesList)
1973 {
1974 if (property.first == "UfmProvisioned")
1975 {
1976 provState = std::get_if<bool>(&property.second);
1977 }
1978 else if (property.first == "UfmLocked")
1979 {
1980 lockState = std::get_if<bool>(&property.second);
1981 }
1982 }
1983
1984 if ((provState == nullptr) || (lockState == nullptr))
1985 {
1986 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1987 messages::internalError(aResp->res);
1988 return;
1989 }
1990
AppaRao Pulia6349912019-10-18 17:16:08 +05301991 if (*provState == true)
1992 {
1993 if (*lockState == true)
1994 {
1995 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1996 }
1997 else
1998 {
1999 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
2000 }
2001 }
2002 else
2003 {
2004 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2005 }
2006 },
2007 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2008 "org.freedesktop.DBus.Properties", "GetAll",
2009 "xyz.openbmc_project.PFR.Attributes");
2010}
2011#endif
2012
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302013/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002014 * @brief Translate the PowerMode to a response message.
2015 *
2016 * @param[in] aResp Shared pointer for generating response message.
2017 * @param[in] modeValue PowerMode value to be translated
2018 *
2019 * @return None.
2020 */
2021inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2022 const std::string& modeValue)
2023{
2024 std::string modeString;
2025
George Liu0fda0f12021-11-16 10:06:17 +08002026 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002027 {
2028 aResp->res.jsonValue["PowerMode"] = "Static";
2029 }
George Liu0fda0f12021-11-16 10:06:17 +08002030 else if (
2031 modeValue ==
2032 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002033 {
2034 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2035 }
George Liu0fda0f12021-11-16 10:06:17 +08002036 else if (modeValue ==
2037 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002038 {
2039 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2040 }
George Liu0fda0f12021-11-16 10:06:17 +08002041 else if (modeValue ==
2042 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002043 {
2044 aResp->res.jsonValue["PowerMode"] = "OEM";
2045 }
2046 else
2047 {
2048 // Any other values would be invalid
2049 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2050 messages::internalError(aResp->res);
2051 }
2052}
2053
2054/**
2055 * @brief Retrieves system power mode
2056 *
2057 * @param[in] aResp Shared pointer for generating response message.
2058 *
2059 * @return None.
2060 */
2061inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2062{
2063 BMCWEB_LOG_DEBUG << "Get power mode.";
2064
2065 // Get Power Mode object path:
2066 crow::connections::systemBus->async_method_call(
2067 [aResp](
2068 const boost::system::error_code ec,
2069 const std::vector<std::pair<
2070 std::string,
2071 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2072 subtree) {
2073 if (ec)
2074 {
2075 BMCWEB_LOG_DEBUG
2076 << "DBUS response error on Power.Mode GetSubTree " << ec;
2077 // This is an optional D-Bus object so just return if
2078 // error occurs
2079 return;
2080 }
2081 if (subtree.empty())
2082 {
2083 // As noted above, this is an optional interface so just return
2084 // if there is no instance found
2085 return;
2086 }
2087 if (subtree.size() > 1)
2088 {
2089 // More then one PowerMode object is not supported and is an
2090 // error
2091 BMCWEB_LOG_DEBUG
2092 << "Found more than 1 system D-Bus Power.Mode objects: "
2093 << subtree.size();
2094 messages::internalError(aResp->res);
2095 return;
2096 }
2097 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2098 {
2099 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2100 messages::internalError(aResp->res);
2101 return;
2102 }
2103 const std::string& path = subtree[0].first;
2104 const std::string& service = subtree[0].second.begin()->first;
2105 if (service.empty())
2106 {
2107 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2108 messages::internalError(aResp->res);
2109 return;
2110 }
2111 // Valid Power Mode object found, now read the current value
2112 crow::connections::systemBus->async_method_call(
2113 [aResp](const boost::system::error_code ec,
2114 const std::variant<std::string>& pmode) {
2115 if (ec)
2116 {
2117 BMCWEB_LOG_DEBUG
2118 << "DBUS response error on PowerMode Get: " << ec;
2119 messages::internalError(aResp->res);
2120 return;
2121 }
2122
2123 const std::string* s = std::get_if<std::string>(&pmode);
2124 if (s == nullptr)
2125 {
2126 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2127 messages::internalError(aResp->res);
2128 return;
2129 }
2130
2131 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2132 {"Static", "MaximumPerformance", "PowerSaving"};
2133
2134 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2135 translatePowerMode(aResp, *s);
2136 },
2137 service, path, "org.freedesktop.DBus.Properties", "Get",
2138 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2139 },
2140 "xyz.openbmc_project.ObjectMapper",
2141 "/xyz/openbmc_project/object_mapper",
2142 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2143 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2144}
2145
2146/**
2147 * @brief Validate the specified mode is valid and return the PowerMode
2148 * name associated with that string
2149 *
2150 * @param[in] aResp Shared pointer for generating response message.
2151 * @param[in] modeString String representing the desired PowerMode
2152 *
2153 * @return PowerMode value or empty string if mode is not valid
2154 */
2155inline std::string
2156 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2157 const std::string& modeString)
2158{
2159 std::string mode;
2160
2161 if (modeString == "Static")
2162 {
2163 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2164 }
2165 else if (modeString == "MaximumPerformance")
2166 {
George Liu0fda0f12021-11-16 10:06:17 +08002167 mode =
2168 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002169 }
2170 else if (modeString == "PowerSaving")
2171 {
2172 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2173 }
2174 else
2175 {
2176 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2177 }
2178 return mode;
2179}
2180
2181/**
2182 * @brief Sets system power mode.
2183 *
2184 * @param[in] aResp Shared pointer for generating response message.
2185 * @param[in] pmode System power mode from request.
2186 *
2187 * @return None.
2188 */
2189inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2190 const std::string& pmode)
2191{
2192 BMCWEB_LOG_DEBUG << "Set power mode.";
2193
2194 std::string powerMode = validatePowerMode(aResp, pmode);
2195 if (powerMode.empty())
2196 {
2197 return;
2198 }
2199
2200 // Get Power Mode object path:
2201 crow::connections::systemBus->async_method_call(
2202 [aResp, powerMode](
2203 const boost::system::error_code ec,
2204 const std::vector<std::pair<
2205 std::string,
2206 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2207 subtree) {
2208 if (ec)
2209 {
2210 BMCWEB_LOG_DEBUG
2211 << "DBUS response error on Power.Mode GetSubTree " << ec;
2212 // This is an optional D-Bus object, but user attempted to patch
2213 messages::internalError(aResp->res);
2214 return;
2215 }
2216 if (subtree.empty())
2217 {
2218 // This is an optional D-Bus object, but user attempted to patch
2219 messages::resourceNotFound(aResp->res, "ComputerSystem",
2220 "PowerMode");
2221 return;
2222 }
2223 if (subtree.size() > 1)
2224 {
2225 // More then one PowerMode object is not supported and is an
2226 // error
2227 BMCWEB_LOG_DEBUG
2228 << "Found more than 1 system D-Bus Power.Mode objects: "
2229 << subtree.size();
2230 messages::internalError(aResp->res);
2231 return;
2232 }
2233 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2234 {
2235 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2236 messages::internalError(aResp->res);
2237 return;
2238 }
2239 const std::string& path = subtree[0].first;
2240 const std::string& service = subtree[0].second.begin()->first;
2241 if (service.empty())
2242 {
2243 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2244 messages::internalError(aResp->res);
2245 return;
2246 }
2247
2248 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2249 << path;
2250
2251 // Set the Power Mode property
2252 crow::connections::systemBus->async_method_call(
2253 [aResp](const boost::system::error_code ec) {
2254 if (ec)
2255 {
2256 messages::internalError(aResp->res);
2257 return;
2258 }
2259 },
2260 service, path, "org.freedesktop.DBus.Properties", "Set",
2261 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2262 std::variant<std::string>(powerMode));
2263 },
2264 "xyz.openbmc_project.ObjectMapper",
2265 "/xyz/openbmc_project/object_mapper",
2266 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2267 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2268}
2269
2270/**
Yong Li51709ff2019-09-30 14:13:04 +08002271 * @brief Translates watchdog timeout action DBUS property value to redfish.
2272 *
2273 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2274 *
2275 * @return Returns as a string, the timeout action in Redfish terms. If
2276 * translation cannot be done, returns an empty string.
2277 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002278inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002279{
2280 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2281 {
2282 return "None";
2283 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002284 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002285 {
2286 return "ResetSystem";
2287 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002288 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002289 {
2290 return "PowerDown";
2291 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002292 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002293 {
2294 return "PowerCycle";
2295 }
2296
2297 return "";
2298}
2299
2300/**
Yong Lic45f0082019-10-10 14:19:01 +08002301 *@brief Translates timeout action from Redfish to DBUS property value.
2302 *
2303 *@param[in] rfAction The timeout action in Redfish.
2304 *
2305 *@return Returns as a string, the time_out action as expected by DBUS.
2306 *If translation cannot be done, returns an empty string.
2307 */
2308
Ed Tanous23a21a12020-07-25 04:45:05 +00002309inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002310{
2311 if (rfAction == "None")
2312 {
2313 return "xyz.openbmc_project.State.Watchdog.Action.None";
2314 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002315 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002316 {
2317 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2318 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002319 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002320 {
2321 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2322 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002323 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002324 {
2325 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2326 }
2327
2328 return "";
2329}
2330
2331/**
Yong Li51709ff2019-09-30 14:13:04 +08002332 * @brief Retrieves host watchdog timer properties over DBUS
2333 *
2334 * @param[in] aResp Shared pointer for completing asynchronous calls.
2335 *
2336 * @return None.
2337 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002338inline void
2339 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002340{
2341 BMCWEB_LOG_DEBUG << "Get host watchodg";
2342 crow::connections::systemBus->async_method_call(
2343 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002344 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002345 if (ec)
2346 {
2347 // watchdog service is stopped
2348 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2349 return;
2350 }
2351
2352 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2353
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002354 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002355 aResp->res.jsonValue["HostWatchdogTimer"];
2356
2357 // watchdog service is running/enabled
2358 hostWatchdogTimer["Status"]["State"] = "Enabled";
2359
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002360 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002361 {
2362 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2363 if (property.first == "Enabled")
2364 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002365 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002366
2367 if (!state)
2368 {
2369 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002370 return;
Yong Li51709ff2019-09-30 14:13:04 +08002371 }
2372
2373 hostWatchdogTimer["FunctionEnabled"] = *state;
2374 }
2375 else if (property.first == "ExpireAction")
2376 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002377 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002378 std::get_if<std::string>(&property.second);
2379 if (!s)
2380 {
2381 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002382 return;
Yong Li51709ff2019-09-30 14:13:04 +08002383 }
2384
2385 std::string action = dbusToRfWatchdogAction(*s);
2386 if (action.empty())
2387 {
2388 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002389 return;
Yong Li51709ff2019-09-30 14:13:04 +08002390 }
2391 hostWatchdogTimer["TimeoutAction"] = action;
2392 }
2393 }
2394 },
2395 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2396 "org.freedesktop.DBus.Properties", "GetAll",
2397 "xyz.openbmc_project.State.Watchdog");
2398}
2399
2400/**
Yong Lic45f0082019-10-10 14:19:01 +08002401 * @brief Sets Host WatchDog Timer properties.
2402 *
2403 * @param[in] aResp Shared pointer for generating response message.
2404 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2405 * RF request.
2406 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2407 *
2408 * @return None.
2409 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002410inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002411 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002412 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002413{
2414 BMCWEB_LOG_DEBUG << "Set host watchdog";
2415
2416 if (wdtTimeOutAction)
2417 {
2418 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2419 // check if TimeOut Action is Valid
2420 if (wdtTimeOutActStr.empty())
2421 {
2422 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2423 << *wdtTimeOutAction;
2424 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2425 "TimeoutAction");
2426 return;
2427 }
2428
2429 crow::connections::systemBus->async_method_call(
2430 [aResp](const boost::system::error_code ec) {
2431 if (ec)
2432 {
2433 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2434 messages::internalError(aResp->res);
2435 return;
2436 }
2437 },
2438 "xyz.openbmc_project.Watchdog",
2439 "/xyz/openbmc_project/watchdog/host0",
2440 "org.freedesktop.DBus.Properties", "Set",
2441 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2442 std::variant<std::string>(wdtTimeOutActStr));
2443 }
2444
2445 if (wdtEnable)
2446 {
2447 crow::connections::systemBus->async_method_call(
2448 [aResp](const boost::system::error_code ec) {
2449 if (ec)
2450 {
2451 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2452 messages::internalError(aResp->res);
2453 return;
2454 }
2455 },
2456 "xyz.openbmc_project.Watchdog",
2457 "/xyz/openbmc_project/watchdog/host0",
2458 "org.freedesktop.DBus.Properties", "Set",
2459 "xyz.openbmc_project.State.Watchdog", "Enabled",
2460 std::variant<bool>(*wdtEnable));
2461 }
2462}
2463
Chris Cain37bbf982021-09-20 10:53:09 -05002464using ipsPropertiesType =
2465 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2466/**
2467 * @brief Parse the Idle Power Saver properties into json
2468 *
2469 * @param[in] aResp Shared pointer for completing asynchronous calls.
2470 * @param[in] properties IPS property data from DBus.
2471 *
2472 * @return true if successful
2473 */
Ed Tanousf6674222021-11-13 09:41:41 -08002474inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2475 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002476{
2477 for (const auto& property : properties)
2478 {
2479 if (property.first == "Enabled")
2480 {
2481 const bool* state = std::get_if<bool>(&property.second);
2482 if (!state)
2483 {
2484 return false;
2485 }
2486 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2487 }
2488 else if (property.first == "EnterUtilizationPercent")
2489 {
2490 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2491 if (!util)
2492 {
2493 return false;
2494 }
2495 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2496 }
2497 else if (property.first == "EnterDwellTime")
2498 {
2499 // Convert Dbus time from milliseconds to seconds
2500 const uint64_t* timeMilliseconds =
2501 std::get_if<uint64_t>(&property.second);
2502 if (!timeMilliseconds)
2503 {
2504 return false;
2505 }
2506 const std::chrono::duration<uint64_t, std::milli> ms(
2507 *timeMilliseconds);
2508 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2509 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2510 .count();
2511 }
2512 else if (property.first == "ExitUtilizationPercent")
2513 {
2514 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2515 if (!util)
2516 {
2517 return false;
2518 }
2519 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2520 }
2521 else if (property.first == "ExitDwellTime")
2522 {
2523 // Convert Dbus time from milliseconds to seconds
2524 const uint64_t* timeMilliseconds =
2525 std::get_if<uint64_t>(&property.second);
2526 if (!timeMilliseconds)
2527 {
2528 return false;
2529 }
2530 const std::chrono::duration<uint64_t, std::milli> ms(
2531 *timeMilliseconds);
2532 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2533 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2534 .count();
2535 }
2536 else
2537 {
2538 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2539 << property.first;
2540 }
2541 }
2542
2543 return true;
2544}
2545
2546/**
2547 * @brief Retrieves host watchdog timer properties over DBUS
2548 *
2549 * @param[in] aResp Shared pointer for completing asynchronous calls.
2550 *
2551 * @return None.
2552 */
2553inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2554{
2555 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2556
2557 // Get IdlePowerSaver object path:
2558 crow::connections::systemBus->async_method_call(
2559 [aResp](
2560 const boost::system::error_code ec,
2561 const std::vector<std::pair<
2562 std::string,
2563 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2564 subtree) {
2565 if (ec)
2566 {
2567 BMCWEB_LOG_DEBUG
2568 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2569 << ec;
2570 messages::internalError(aResp->res);
2571 return;
2572 }
2573 if (subtree.empty())
2574 {
2575 // This is an optional interface so just return
2576 // if there is no instance found
2577 BMCWEB_LOG_DEBUG << "No instances found";
2578 return;
2579 }
2580 if (subtree.size() > 1)
2581 {
2582 // More then one PowerIdlePowerSaver object is not supported and
2583 // is an error
2584 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2585 "Power.IdlePowerSaver objects: "
2586 << subtree.size();
2587 messages::internalError(aResp->res);
2588 return;
2589 }
2590 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2591 {
2592 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2593 messages::internalError(aResp->res);
2594 return;
2595 }
2596 const std::string& path = subtree[0].first;
2597 const std::string& service = subtree[0].second.begin()->first;
2598 if (service.empty())
2599 {
2600 BMCWEB_LOG_DEBUG
2601 << "Power.IdlePowerSaver service mapper error!";
2602 messages::internalError(aResp->res);
2603 return;
2604 }
2605
2606 // Valid IdlePowerSaver object found, now read the current values
2607 crow::connections::systemBus->async_method_call(
2608 [aResp](const boost::system::error_code ec,
2609 ipsPropertiesType& properties) {
2610 if (ec)
2611 {
2612 BMCWEB_LOG_ERROR
2613 << "DBUS response error on IdlePowerSaver GetAll: "
2614 << ec;
2615 messages::internalError(aResp->res);
2616 return;
2617 }
2618
2619 if (parseIpsProperties(aResp, properties) == false)
2620 {
2621 messages::internalError(aResp->res);
2622 return;
2623 }
2624 },
2625 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2626 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2627 },
2628 "xyz.openbmc_project.ObjectMapper",
2629 "/xyz/openbmc_project/object_mapper",
2630 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2631 std::array<const char*, 1>{
2632 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2633
2634 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2635}
2636
2637/**
2638 * @brief Sets Idle Power Saver properties.
2639 *
2640 * @param[in] aResp Shared pointer for generating response message.
2641 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2642 * RF request.
2643 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2644 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2645 * before entering idle state.
2646 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2647 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2648 * before exiting idle state
2649 *
2650 * @return None.
2651 */
2652inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2653 const std::optional<bool> ipsEnable,
2654 const std::optional<uint8_t> ipsEnterUtil,
2655 const std::optional<uint64_t> ipsEnterTime,
2656 const std::optional<uint8_t> ipsExitUtil,
2657 const std::optional<uint64_t> ipsExitTime)
2658{
2659 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2660
2661 // Get IdlePowerSaver object path:
2662 crow::connections::systemBus->async_method_call(
2663 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2664 ipsExitTime](
2665 const boost::system::error_code ec,
2666 const std::vector<std::pair<
2667 std::string,
2668 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2669 subtree) {
2670 if (ec)
2671 {
2672 BMCWEB_LOG_DEBUG
2673 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2674 << ec;
2675 messages::internalError(aResp->res);
2676 return;
2677 }
2678 if (subtree.empty())
2679 {
2680 // This is an optional D-Bus object, but user attempted to patch
2681 messages::resourceNotFound(aResp->res, "ComputerSystem",
2682 "IdlePowerSaver");
2683 return;
2684 }
2685 if (subtree.size() > 1)
2686 {
2687 // More then one PowerIdlePowerSaver object is not supported and
2688 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002689 BMCWEB_LOG_DEBUG
2690 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2691 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002692 messages::internalError(aResp->res);
2693 return;
2694 }
2695 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2696 {
2697 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2698 messages::internalError(aResp->res);
2699 return;
2700 }
2701 const std::string& path = subtree[0].first;
2702 const std::string& service = subtree[0].second.begin()->first;
2703 if (service.empty())
2704 {
2705 BMCWEB_LOG_DEBUG
2706 << "Power.IdlePowerSaver service mapper error!";
2707 messages::internalError(aResp->res);
2708 return;
2709 }
2710
2711 // Valid Power IdlePowerSaver object found, now set any values that
2712 // need to be updated
2713
2714 if (ipsEnable)
2715 {
2716 crow::connections::systemBus->async_method_call(
2717 [aResp](const boost::system::error_code ec) {
2718 if (ec)
2719 {
2720 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2721 messages::internalError(aResp->res);
2722 return;
2723 }
2724 },
2725 service, path, "org.freedesktop.DBus.Properties", "Set",
2726 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2727 "Enabled", std::variant<bool>(*ipsEnable));
2728 }
2729 if (ipsEnterUtil)
2730 {
2731 crow::connections::systemBus->async_method_call(
2732 [aResp](const boost::system::error_code ec) {
2733 if (ec)
2734 {
2735 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2736 messages::internalError(aResp->res);
2737 return;
2738 }
2739 },
2740 service, path, "org.freedesktop.DBus.Properties", "Set",
2741 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2742 "EnterUtilizationPercent",
2743 std::variant<uint8_t>(*ipsEnterUtil));
2744 }
2745 if (ipsEnterTime)
2746 {
2747 // Convert from seconds into milliseconds for DBus
2748 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2749 crow::connections::systemBus->async_method_call(
2750 [aResp](const boost::system::error_code ec) {
2751 if (ec)
2752 {
2753 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2754 messages::internalError(aResp->res);
2755 return;
2756 }
2757 },
2758 service, path, "org.freedesktop.DBus.Properties", "Set",
2759 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2760 "EnterDwellTime", std::variant<uint64_t>(timeMilliseconds));
2761 }
2762 if (ipsExitUtil)
2763 {
2764 crow::connections::systemBus->async_method_call(
2765 [aResp](const boost::system::error_code ec) {
2766 if (ec)
2767 {
2768 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2769 messages::internalError(aResp->res);
2770 return;
2771 }
2772 },
2773 service, path, "org.freedesktop.DBus.Properties", "Set",
2774 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2775 "ExitUtilizationPercent",
2776 std::variant<uint8_t>(*ipsExitUtil));
2777 }
2778 if (ipsExitTime)
2779 {
2780 // Convert from seconds into milliseconds for DBus
2781 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2782 crow::connections::systemBus->async_method_call(
2783 [aResp](const boost::system::error_code ec) {
2784 if (ec)
2785 {
2786 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2787 messages::internalError(aResp->res);
2788 return;
2789 }
2790 },
2791 service, path, "org.freedesktop.DBus.Properties", "Set",
2792 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2793 "ExitDwellTime", std::variant<uint64_t>(timeMilliseconds));
2794 }
2795 },
2796 "xyz.openbmc_project.ObjectMapper",
2797 "/xyz/openbmc_project/object_mapper",
2798 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2799 std::array<const char*, 1>{
2800 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2801
2802 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2803}
2804
Yong Lic45f0082019-10-10 14:19:01 +08002805/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002806 * SystemsCollection derived class for delivering ComputerSystems Collection
2807 * Schema
2808 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002809inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002810{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002811 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002812 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002813 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002814 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002815 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2816 asyncResp->res.jsonValue["@odata.type"] =
2817 "#ComputerSystemCollection.ComputerSystemCollection";
2818 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2819 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002820
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002821 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002822 [asyncResp](const boost::system::error_code ec,
2823 const std::variant<std::string>& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002824 nlohmann::json& ifaceArray =
2825 asyncResp->res.jsonValue["Members"];
2826 ifaceArray = nlohmann::json::array();
2827 auto& count =
2828 asyncResp->res.jsonValue["Members@odata.count"];
2829 ifaceArray.push_back(
2830 {{"@odata.id", "/redfish/v1/Systems/system"}});
2831 count = ifaceArray.size();
2832 if (!ec)
2833 {
2834 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2835 ifaceArray.push_back(
2836 {{"@odata.id",
2837 "/redfish/v1/Systems/hypervisor"}});
2838 count = ifaceArray.size();
2839 }
2840 },
2841 "xyz.openbmc_project.Settings",
2842 "/xyz/openbmc_project/network/hypervisor",
2843 "org.freedesktop.DBus.Properties", "Get",
2844 "xyz.openbmc_project.Network.SystemConfiguration",
2845 "HostName");
2846 });
2847}
Sunitha Harish462023a2020-02-19 08:34:59 -06002848
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002849/**
2850 * Function transceives data with dbus directly.
2851 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002852inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002853{
2854 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2855 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2856 constexpr char const* interfaceName =
2857 "xyz.openbmc_project.Control.Host.NMI";
2858 constexpr char const* method = "NMI";
2859
2860 crow::connections::systemBus->async_method_call(
2861 [asyncResp](const boost::system::error_code ec) {
2862 if (ec)
2863 {
2864 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2865 messages::internalError(asyncResp->res);
2866 return;
2867 }
2868 messages::success(asyncResp->res);
2869 },
2870 serviceName, objectPath, interfaceName, method);
2871}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002872
2873/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002874 * SystemActionsReset class supports handle POST method for Reset action.
2875 * The class retrieves and sends data directly to D-Bus.
2876 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002877inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002878{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002879 /**
2880 * Function handles POST method request.
2881 * Analyzes POST body message before sends Reset request data to D-Bus.
2882 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002883 BMCWEB_ROUTE(app,
2884 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002885 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002886 .methods(
2887 boost::beast::http::verb::
2888 post)([](const crow::Request& req,
2889 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2890 std::string resetType;
2891 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2892 resetType))
2893 {
2894 return;
2895 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002896
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002897 // Get the command and host vs. chassis
2898 std::string command;
2899 bool hostCommand;
2900 if ((resetType == "On") || (resetType == "ForceOn"))
2901 {
2902 command = "xyz.openbmc_project.State.Host.Transition.On";
2903 hostCommand = true;
2904 }
2905 else if (resetType == "ForceOff")
2906 {
2907 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2908 hostCommand = false;
2909 }
2910 else if (resetType == "ForceRestart")
2911 {
2912 command =
2913 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2914 hostCommand = true;
2915 }
2916 else if (resetType == "GracefulShutdown")
2917 {
2918 command = "xyz.openbmc_project.State.Host.Transition.Off";
2919 hostCommand = true;
2920 }
2921 else if (resetType == "GracefulRestart")
2922 {
George Liu0fda0f12021-11-16 10:06:17 +08002923 command =
2924 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002925 hostCommand = true;
2926 }
2927 else if (resetType == "PowerCycle")
2928 {
2929 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2930 hostCommand = true;
2931 }
2932 else if (resetType == "Nmi")
2933 {
2934 doNMI(asyncResp);
2935 return;
2936 }
2937 else
2938 {
2939 messages::actionParameterUnknown(asyncResp->res, "Reset",
2940 resetType);
2941 return;
2942 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002943
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002944 if (hostCommand)
2945 {
2946 crow::connections::systemBus->async_method_call(
2947 [asyncResp, resetType](const boost::system::error_code ec) {
2948 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002949 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002950 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2951 if (ec.value() ==
2952 boost::asio::error::invalid_argument)
2953 {
2954 messages::actionParameterNotSupported(
2955 asyncResp->res, resetType, "Reset");
2956 }
2957 else
2958 {
2959 messages::internalError(asyncResp->res);
2960 }
2961 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002962 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002963 messages::success(asyncResp->res);
2964 },
2965 "xyz.openbmc_project.State.Host",
2966 "/xyz/openbmc_project/state/host0",
2967 "org.freedesktop.DBus.Properties", "Set",
2968 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2969 std::variant<std::string>{command});
2970 }
2971 else
2972 {
2973 crow::connections::systemBus->async_method_call(
2974 [asyncResp, resetType](const boost::system::error_code ec) {
2975 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002976 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002977 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2978 if (ec.value() ==
2979 boost::asio::error::invalid_argument)
2980 {
2981 messages::actionParameterNotSupported(
2982 asyncResp->res, resetType, "Reset");
2983 }
2984 else
2985 {
2986 messages::internalError(asyncResp->res);
2987 }
2988 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002989 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002990 messages::success(asyncResp->res);
2991 },
2992 "xyz.openbmc_project.State.Chassis",
2993 "/xyz/openbmc_project/state/chassis0",
2994 "org.freedesktop.DBus.Properties", "Set",
2995 "xyz.openbmc_project.State.Chassis",
2996 "RequestedPowerTransition",
2997 std::variant<std::string>{command});
2998 }
2999 });
3000}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003001
3002/**
Ed Tanous66173382018-08-15 18:20:59 -07003003 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003004 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003005inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003006{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003007
Ed Tanous1abe55e2018-09-05 08:30:59 -07003008 /**
3009 * Functions triggers appropriate requests on DBus
3010 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003011 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003012 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003013 .methods(
3014 boost::beast::http::verb::
3015 get)([](const crow::Request&,
3016 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3017 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05003018 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003019 asyncResp->res.jsonValue["Name"] = "system";
3020 asyncResp->res.jsonValue["Id"] = "system";
3021 asyncResp->res.jsonValue["SystemType"] = "Physical";
3022 asyncResp->res.jsonValue["Description"] = "Computer System";
3023 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3024 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3025 "Disabled";
3026 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3027 uint64_t(0);
3028 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3029 "Disabled";
3030 asyncResp->res.jsonValue["@odata.id"] =
3031 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003032
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003033 asyncResp->res.jsonValue["Processors"] = {
3034 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
3035 asyncResp->res.jsonValue["Memory"] = {
3036 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
3037 asyncResp->res.jsonValue["Storage"] = {
3038 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08003039
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003040 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
3041 {"target",
3042 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
3043 {"@Redfish.ActionInfo",
3044 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003045
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003046 asyncResp->res.jsonValue["LogServices"] = {
3047 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003048
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003049 asyncResp->res.jsonValue["Bios"] = {
3050 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08003051
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003052 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
3053 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08003054
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003055 asyncResp->res.jsonValue["Status"] = {
3056 {"Health", "OK"},
3057 {"State", "Enabled"},
3058 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003059
3060 // Fill in SerialConsole info
3061 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
3062 15;
3063 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
3064 {"ServiceEnabled", true},
3065 };
3066 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3067 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
3068 {"ServiceEnabled", true},
3069 {"Port", 2200},
3070 // https://github.com/openbmc/docs/blob/master/console.md
3071 {"HotKeySequenceDisplay", "Press ~. to exit console"},
3072 };
3073
3074#ifdef BMCWEB_ENABLE_KVM
3075 // Fill in GraphicalConsole info
3076 asyncResp->res.jsonValue["GraphicalConsole"] = {
3077 {"ServiceEnabled", true},
3078 {"MaxConcurrentSessions", 4},
3079 {"ConnectTypesSupported", {"KVMIP"}},
3080 };
3081#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003082 constexpr const std::array<const char*, 4> inventoryForSystems = {
3083 "xyz.openbmc_project.Inventory.Item.Dimm",
3084 "xyz.openbmc_project.Inventory.Item.Cpu",
3085 "xyz.openbmc_project.Inventory.Item.Drive",
3086 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003087
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003088 auto health = std::make_shared<HealthPopulate>(asyncResp);
3089 crow::connections::systemBus->async_method_call(
3090 [health](const boost::system::error_code ec,
3091 std::vector<std::string>& resp) {
3092 if (ec)
3093 {
3094 // no inventory
3095 return;
3096 }
3097
3098 health->inventory = std::move(resp);
3099 },
3100 "xyz.openbmc_project.ObjectMapper",
3101 "/xyz/openbmc_project/object_mapper",
3102 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
3103 int32_t(0), inventoryForSystems);
3104
3105 health->populate();
3106
3107 getMainChassisId(
3108 asyncResp, [](const std::string& chassisId,
3109 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3110 aRsp->res.jsonValue["Links"]["Chassis"] = {
3111 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
3112 });
3113
3114 getLocationIndicatorActive(asyncResp);
3115 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3116 getIndicatorLedState(asyncResp);
3117 getComputerSystem(asyncResp, health);
3118 getHostState(asyncResp);
3119 getBootProperties(asyncResp);
3120 getBootProgress(asyncResp);
3121 getPCIeDeviceList(asyncResp, "PCIeDevices");
3122 getHostWatchdogTimer(asyncResp);
3123 getPowerRestorePolicy(asyncResp);
3124 getAutomaticRetry(asyncResp);
3125 getLastResetTime(asyncResp);
3126#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
3127 getProvisioningStatus(asyncResp);
3128#endif
Ali Ahmed19817712021-06-29 17:01:52 -05003129 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05003130 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003131 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003132 });
3133 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003134 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003135 .methods(boost::beast::http::verb::patch)(
3136 [](const crow::Request& req,
3137 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3138 std::optional<bool> locationIndicatorActive;
3139 std::optional<std::string> indicatorLed;
3140 std::optional<nlohmann::json> bootProps;
3141 std::optional<nlohmann::json> wdtTimerProps;
3142 std::optional<std::string> assetTag;
3143 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003144 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003145 std::optional<nlohmann::json> ipsProps;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003146 if (!json_util::readJson(
3147 req, asyncResp->res, "IndicatorLED", indicatorLed,
3148 "LocationIndicatorActive", locationIndicatorActive,
3149 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3150 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003151 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3152 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003153 {
James Feistb49ac872019-05-21 15:12:01 -07003154 return;
3155 }
3156
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003157 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003158
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003159 if (assetTag)
3160 {
3161 setAssetTag(asyncResp, *assetTag);
3162 }
James Feistb49ac872019-05-21 15:12:01 -07003163
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003164 if (wdtTimerProps)
3165 {
3166 std::optional<bool> wdtEnable;
3167 std::optional<std::string> wdtTimeOutAction;
3168
3169 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3170 "FunctionEnabled", wdtEnable,
3171 "TimeoutAction", wdtTimeOutAction))
3172 {
3173 return;
3174 }
3175 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3176 }
3177
3178 if (bootProps)
3179 {
3180 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003181 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003182 std::optional<std::string> bootEnable;
3183 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003184 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003185
3186 if (!json_util::readJson(
3187 *bootProps, asyncResp->res,
3188 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003189 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003190 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003191 "AutomaticRetryConfig", automaticRetryConfig,
3192 "TrustedModuleRequiredToBoot",
3193 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003194 {
3195 return;
3196 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003197
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003198 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003199 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003200 setBootProperties(asyncResp, bootSource, bootType,
3201 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003202 }
3203 if (automaticRetryConfig)
3204 {
3205 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3206 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003207
3208 if (trustedModuleRequiredToBoot)
3209 {
3210 setTrustedModuleRequiredToBoot(
3211 asyncResp, *trustedModuleRequiredToBoot);
3212 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003213 }
3214
3215 if (locationIndicatorActive)
3216 {
3217 setLocationIndicatorActive(asyncResp,
3218 *locationIndicatorActive);
3219 }
3220
3221 // TODO (Gunnar): Remove IndicatorLED after enough time has
3222 // passed
3223 if (indicatorLed)
3224 {
3225 setIndicatorLedState(asyncResp, *indicatorLed);
3226 asyncResp->res.addHeader(
3227 boost::beast::http::field::warning,
3228 "299 - \"IndicatorLED is deprecated. Use "
3229 "LocationIndicatorActive instead.\"");
3230 }
3231
3232 if (powerRestorePolicy)
3233 {
3234 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3235 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003236
3237 if (powerMode)
3238 {
3239 setPowerMode(asyncResp, *powerMode);
3240 }
Chris Cain37bbf982021-09-20 10:53:09 -05003241
3242 if (ipsProps)
3243 {
3244 std::optional<bool> ipsEnable;
3245 std::optional<uint8_t> ipsEnterUtil;
3246 std::optional<uint64_t> ipsEnterTime;
3247 std::optional<uint8_t> ipsExitUtil;
3248 std::optional<uint64_t> ipsExitTime;
3249
3250 if (!json_util::readJson(
3251 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3252 "EnterUtilizationPercent", ipsEnterUtil,
3253 "EnterDwellTimeSeconds", ipsEnterTime,
3254 "ExitUtilizationPercent", ipsExitUtil,
3255 "ExitDwellTimeSeconds", ipsExitTime))
3256 {
3257 return;
3258 }
3259 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3260 ipsEnterTime, ipsExitUtil, ipsExitTime);
3261 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003262 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003263}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303264
3265/**
3266 * SystemResetActionInfo derived class for delivering Computer Systems
3267 * ResetType AllowableValues using ResetInfo schema.
3268 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003269inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303270{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303271
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303272 /**
3273 * Functions triggers appropriate requests on DBus
3274 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003275 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003276 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003277 .methods(boost::beast::http::verb::get)(
3278 [](const crow::Request&,
3279 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3280 asyncResp->res.jsonValue = {
3281 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3282 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3283 {"Name", "Reset Action Info"},
3284 {"Id", "ResetActionInfo"},
3285 {"Parameters",
3286 {{{"Name", "ResetType"},
3287 {"Required", true},
3288 {"DataType", "String"},
3289 {"AllowableValues",
3290 {"On", "ForceOff", "ForceOn", "ForceRestart",
3291 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3292 "Nmi"}}}}}};
3293 });
3294}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003295} // namespace redfish