blob: 8e1a6f407908350541c4d5a4dce7de0f1969e01e [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
Nan Zhou1d8782e2021-11-29 22:23:18 -08001174 uint64_t lastResetTimeStamp = *lastResetTimePtr / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001175
1176 // Convert to ISO 8601 standard
1177 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001178 crow::utility::getDateTimeUint(lastResetTimeStamp);
Gunnar Millsc0557e12020-06-30 11:26:20 -05001179 },
1180 "xyz.openbmc_project.State.Chassis",
1181 "/xyz/openbmc_project/state/chassis0",
1182 "org.freedesktop.DBus.Properties", "Get",
1183 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1184}
1185
1186/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001187 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1188 *
1189 * @param[in] aResp Shared pointer for generating response message.
1190 *
1191 * @return None.
1192 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001193inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001194{
1195 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1196
1197 crow::connections::systemBus->async_method_call(
1198 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001199 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001200 if (ec)
1201 {
1202 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1203 return;
1204 }
1205
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001206 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001207 std::get_if<bool>(&autoRebootEnabled);
1208
1209 if (!autoRebootEnabledPtr)
1210 {
1211 messages::internalError(aResp->res);
1212 return;
1213 }
1214
1215 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1216 if (*autoRebootEnabledPtr == true)
1217 {
1218 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1219 "RetryAttempts";
1220 // If AutomaticRetry (AutoReboot) is enabled see how many
1221 // attempts are left
1222 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001223 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001224 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001225 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001226 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001227 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001228 return;
1229 }
1230
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001231 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001232 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1233
1234 if (!autoRebootAttemptsLeftPtr)
1235 {
1236 messages::internalError(aResp->res);
1237 return;
1238 }
1239
1240 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1241 << *autoRebootAttemptsLeftPtr;
1242
1243 aResp->res
1244 .jsonValue["Boot"]
1245 ["RemainingAutomaticRetryAttempts"] =
1246 *autoRebootAttemptsLeftPtr;
1247 },
1248 "xyz.openbmc_project.State.Host",
1249 "/xyz/openbmc_project/state/host0",
1250 "org.freedesktop.DBus.Properties", "Get",
1251 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1252 "AttemptsLeft");
1253 }
1254 else
1255 {
1256 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1257 "Disabled";
1258 }
1259
1260 // Not on D-Bus. Hardcoded here:
1261 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1262 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001263
1264 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1265 // and RetryAttempts. OpenBMC only supports Disabled and
1266 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001267 aResp->res
1268 .jsonValue["Boot"]
1269 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1270 "Disabled", "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001271 },
1272 "xyz.openbmc_project.Settings",
1273 "/xyz/openbmc_project/control/host0/auto_reboot",
1274 "org.freedesktop.DBus.Properties", "Get",
1275 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1276}
1277
1278/**
George Liuc6a620f2020-04-10 17:18:11 +08001279 * @brief Retrieves power restore policy over DBUS.
1280 *
1281 * @param[in] aResp Shared pointer for generating response message.
1282 *
1283 * @return None.
1284 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001285inline void
1286 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001287{
1288 BMCWEB_LOG_DEBUG << "Get power restore policy";
1289
1290 crow::connections::systemBus->async_method_call(
1291 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001292 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001293 if (ec)
1294 {
1295 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1296 return;
1297 }
1298
George Liu0fda0f12021-11-16 10:06:17 +08001299 const boost::container::flat_map<std::string, std::string> policyMaps = {
1300 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1301 "AlwaysOn"},
1302 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1303 "AlwaysOff"},
1304 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1305 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001306
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001307 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001308
1309 if (!policyPtr)
1310 {
1311 messages::internalError(aResp->res);
1312 return;
1313 }
1314
1315 auto policyMapsIt = policyMaps.find(*policyPtr);
1316 if (policyMapsIt == policyMaps.end())
1317 {
1318 messages::internalError(aResp->res);
1319 return;
1320 }
1321
1322 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1323 },
1324 "xyz.openbmc_project.Settings",
1325 "/xyz/openbmc_project/control/host0/power_restore_policy",
1326 "org.freedesktop.DBus.Properties", "Get",
1327 "xyz.openbmc_project.Control.Power.RestorePolicy",
1328 "PowerRestorePolicy");
1329}
1330
1331/**
Ali Ahmed19817712021-06-29 17:01:52 -05001332 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1333 * TPM is required for booting the host.
1334 *
1335 * @param[in] aResp Shared pointer for generating response message.
1336 *
1337 * @return None.
1338 */
1339inline void getTrustedModuleRequiredToBoot(
1340 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1341{
1342 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1343
1344 crow::connections::systemBus->async_method_call(
1345 [aResp](
1346 const boost::system::error_code ec,
1347 std::vector<std::pair<
1348 std::string,
1349 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1350 subtree) {
1351 if (ec)
1352 {
1353 BMCWEB_LOG_DEBUG
1354 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1355 // This is an optional D-Bus object so just return if
1356 // error occurs
1357 return;
1358 }
1359 if (subtree.size() == 0)
1360 {
1361 // As noted above, this is an optional interface so just return
1362 // if there is no instance found
1363 return;
1364 }
1365
1366 /* When there is more than one TPMEnable object... */
1367 if (subtree.size() > 1)
1368 {
1369 BMCWEB_LOG_DEBUG
1370 << "DBUS response has more than 1 TPM Enable object:"
1371 << subtree.size();
1372 // Throw an internal Error and return
1373 messages::internalError(aResp->res);
1374 return;
1375 }
1376
1377 // Make sure the Dbus response map has a service and objectPath
1378 // field
1379 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1380 {
1381 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1382 messages::internalError(aResp->res);
1383 return;
1384 }
1385
1386 const std::string& path = subtree[0].first;
1387 const std::string& serv = subtree[0].second.begin()->first;
1388
1389 // Valid TPM Enable object found, now reading the current value
1390 crow::connections::systemBus->async_method_call(
1391 [aResp](const boost::system::error_code ec,
1392 std::variant<bool>& tpmRequired) {
1393 if (ec)
1394 {
1395 BMCWEB_LOG_DEBUG
1396 << "D-BUS response error on TPM.Policy Get" << ec;
1397 messages::internalError(aResp->res);
1398 return;
1399 }
1400
1401 const bool* tpmRequiredVal =
1402 std::get_if<bool>(&tpmRequired);
1403
1404 if (!tpmRequiredVal)
1405 {
1406 messages::internalError(aResp->res);
1407 return;
1408 }
1409
1410 if (*tpmRequiredVal == true)
1411 {
1412 aResp->res
1413 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1414 "Required";
1415 }
1416 else
1417 {
1418 aResp->res
1419 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1420 "Disabled";
1421 }
1422 },
1423 serv, path, "org.freedesktop.DBus.Properties", "Get",
1424 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1425 },
1426 "xyz.openbmc_project.ObjectMapper",
1427 "/xyz/openbmc_project/object_mapper",
1428 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1429 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1430}
1431
1432/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001433 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1434 * TPM is required for booting the host.
1435 *
1436 * @param[in] aResp Shared pointer for generating response message.
1437 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1438 *
1439 * @return None.
1440 */
1441inline void setTrustedModuleRequiredToBoot(
1442 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1443{
1444 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1445
1446 crow::connections::systemBus->async_method_call(
1447 [aResp, tpmRequired](
1448 const boost::system::error_code ec,
1449 std::vector<std::pair<
1450 std::string,
1451 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1452 subtree) {
1453 if (ec)
1454 {
1455 BMCWEB_LOG_DEBUG
1456 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1457 messages::internalError(aResp->res);
1458 return;
1459 }
1460 if (subtree.size() == 0)
1461 {
1462 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1463 "TrustedModuleRequiredToBoot");
1464 return;
1465 }
1466
1467 /* When there is more than one TPMEnable object... */
1468 if (subtree.size() > 1)
1469 {
1470 BMCWEB_LOG_DEBUG
1471 << "DBUS response has more than 1 TPM Enable object:"
1472 << subtree.size();
1473 // Throw an internal Error and return
1474 messages::internalError(aResp->res);
1475 return;
1476 }
1477
1478 // Make sure the Dbus response map has a service and objectPath
1479 // field
1480 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1481 {
1482 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1483 messages::internalError(aResp->res);
1484 return;
1485 }
1486
1487 const std::string& path = subtree[0].first;
1488 const std::string& serv = subtree[0].second.begin()->first;
1489
1490 if (serv.empty())
1491 {
1492 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1493 messages::internalError(aResp->res);
1494 return;
1495 }
1496
1497 // Valid TPM Enable object found, now setting the value
1498 crow::connections::systemBus->async_method_call(
1499 [aResp](const boost::system::error_code ec) {
1500 if (ec)
1501 {
George Liu0fda0f12021-11-16 10:06:17 +08001502 BMCWEB_LOG_DEBUG
1503 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1504 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001505 messages::internalError(aResp->res);
1506 return;
1507 }
1508 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1509 },
1510 serv, path, "org.freedesktop.DBus.Properties", "Set",
1511 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1512 std::variant<bool>(tpmRequired));
1513 },
1514 "xyz.openbmc_project.ObjectMapper",
1515 "/xyz/openbmc_project/object_mapper",
1516 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1517 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1518}
1519
1520/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301521 * @brief Sets boot properties into DBUS object(s).
1522 *
1523 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001524 * @param[in] bootType The boot type to set.
1525 * @return Integer error code.
1526 */
1527inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001528 const std::optional<std::string>& bootType)
1529{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001530 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001531
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001532 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001533 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001534 return;
1535 }
1536
1537 // Source target specified
1538 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1539 // Figure out which DBUS interface and property to use
1540 if (*bootType == "Legacy")
1541 {
1542 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1543 }
1544 else if (*bootType == "UEFI")
1545 {
1546 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1547 }
1548 else
1549 {
1550 BMCWEB_LOG_DEBUG << "Invalid property value for "
1551 "BootSourceOverrideMode: "
1552 << *bootType;
1553 messages::propertyValueNotInList(aResp->res, *bootType,
1554 "BootSourceOverrideMode");
1555 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001556 }
1557
1558 // Act on validated parameters
1559 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1560
1561 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001562 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001563 if (ec)
1564 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001565 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1566 if (ec.value() == boost::asio::error::host_unreachable)
1567 {
1568 messages::resourceNotFound(aResp->res, "Set", "BootType");
1569 return;
1570 }
1571 messages::internalError(aResp->res);
1572 return;
1573 }
1574 BMCWEB_LOG_DEBUG << "Boot type update done.";
1575 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001576 "xyz.openbmc_project.Settings",
1577 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001578 "org.freedesktop.DBus.Properties", "Set",
1579 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1580 std::variant<std::string>(bootTypeStr));
1581}
1582
1583/**
1584 * @brief Sets boot properties into DBUS object(s).
1585 *
1586 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001587 * @param[in] bootType The boot type to set.
1588 * @return Integer error code.
1589 */
1590inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1591 const std::optional<std::string>& bootEnable)
1592{
1593 if (!bootEnable)
1594 {
1595 return;
1596 }
1597 // Source target specified
1598 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1599
1600 bool bootOverrideEnable = false;
1601 bool bootOverridePersistent = false;
1602 // Figure out which DBUS interface and property to use
1603 if (*bootEnable == "Disabled")
1604 {
1605 bootOverrideEnable = false;
1606 }
1607 else if (*bootEnable == "Once")
1608 {
1609 bootOverrideEnable = true;
1610 bootOverridePersistent = false;
1611 }
1612 else if (*bootEnable == "Continuous")
1613 {
1614 bootOverrideEnable = true;
1615 bootOverridePersistent = true;
1616 }
1617 else
1618 {
George Liu0fda0f12021-11-16 10:06:17 +08001619 BMCWEB_LOG_DEBUG
1620 << "Invalid property value for BootSourceOverrideEnabled: "
1621 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001622 messages::propertyValueNotInList(aResp->res, *bootEnable,
1623 "BootSourceOverrideEnabled");
1624 return;
1625 }
1626
1627 // Act on validated parameters
1628 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1629
1630 crow::connections::systemBus->async_method_call(
1631 [aResp](const boost::system::error_code ec) {
1632 if (ec)
1633 {
1634 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1635 messages::internalError(aResp->res);
1636 return;
1637 }
1638 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1639 },
1640 "xyz.openbmc_project.Settings",
1641 "/xyz/openbmc_project/control/host0/boot",
1642 "org.freedesktop.DBus.Properties", "Set",
1643 "xyz.openbmc_project.Object.Enable", "Enabled",
1644 std::variant<bool>(bootOverrideEnable));
1645
1646 if (!bootOverrideEnable)
1647 {
1648 return;
1649 }
1650
1651 // In case boot override is enabled we need to set correct value for the
1652 // 'one_time' enable DBus interface
1653 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1654 << bootOverridePersistent;
1655
1656 crow::connections::systemBus->async_method_call(
1657 [aResp](const boost::system::error_code ec) {
1658 if (ec)
1659 {
1660 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1661 messages::internalError(aResp->res);
1662 return;
1663 }
1664 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1665 },
1666 "xyz.openbmc_project.Settings",
1667 "/xyz/openbmc_project/control/host0/boot/one_time",
1668 "org.freedesktop.DBus.Properties", "Set",
1669 "xyz.openbmc_project.Object.Enable", "Enabled",
1670 std::variant<bool>(!bootOverridePersistent));
1671}
1672
1673/**
1674 * @brief Sets boot properties into DBUS object(s).
1675 *
1676 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301677 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301678 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001679 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301680 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001681inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001682 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301683{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001684 std::string bootSourceStr;
1685 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001686
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001687 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301688 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001689 return;
1690 }
1691
1692 // Source target specified
1693 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1694 // Figure out which DBUS interface and property to use
1695 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1696 {
1697 BMCWEB_LOG_DEBUG
1698 << "Invalid property value for BootSourceOverrideTarget: "
1699 << *bootSource;
1700 messages::propertyValueNotInList(aResp->res, *bootSource,
1701 "BootSourceTargetOverride");
1702 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001703 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301704
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001705 // Act on validated parameters
1706 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1707 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001708
1709 crow::connections::systemBus->async_method_call(
1710 [aResp](const boost::system::error_code ec) {
1711 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301712 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001713 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1714 messages::internalError(aResp->res);
1715 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301716 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001717 BMCWEB_LOG_DEBUG << "Boot source update done.";
1718 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001719 "xyz.openbmc_project.Settings",
1720 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001721 "org.freedesktop.DBus.Properties", "Set",
1722 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1723 std::variant<std::string>(bootSourceStr));
1724
1725 crow::connections::systemBus->async_method_call(
1726 [aResp](const boost::system::error_code ec) {
1727 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301728 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001729 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1730 messages::internalError(aResp->res);
1731 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001733 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1734 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001735 "xyz.openbmc_project.Settings",
1736 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001737 "org.freedesktop.DBus.Properties", "Set",
1738 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1739 std::variant<std::string>(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001740}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001741
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001742/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001743 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301744 *
1745 * @param[in] aResp Shared pointer for generating response message.
1746 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001747 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301748 * @param[in] bootEnable The boot override enable from incoming RF request.
1749 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001750 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301751 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001752
1753inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1754 const std::optional<std::string>& bootSource,
1755 const std::optional<std::string>& bootType,
1756 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301757{
1758 BMCWEB_LOG_DEBUG << "Set boot information.";
1759
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001760 setBootModeOrSource(aResp, bootSource);
1761 setBootType(aResp, bootType);
1762 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301763}
1764
George Liuc6a620f2020-04-10 17:18:11 +08001765/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001766 * @brief Sets AssetTag
1767 *
1768 * @param[in] aResp Shared pointer for generating response message.
1769 * @param[in] assetTag "AssetTag" from request.
1770 *
1771 * @return None.
1772 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001773inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001774 const std::string& assetTag)
1775{
1776 crow::connections::systemBus->async_method_call(
1777 [aResp, assetTag](
1778 const boost::system::error_code ec,
1779 const std::vector<std::pair<
1780 std::string,
1781 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1782 subtree) {
1783 if (ec)
1784 {
1785 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1786 messages::internalError(aResp->res);
1787 return;
1788 }
1789 if (subtree.size() == 0)
1790 {
1791 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1792 messages::internalError(aResp->res);
1793 return;
1794 }
1795 // Assume only 1 system D-Bus object
1796 // Throw an error if there is more than 1
1797 if (subtree.size() > 1)
1798 {
1799 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1800 messages::internalError(aResp->res);
1801 return;
1802 }
1803 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1804 {
1805 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1806 messages::internalError(aResp->res);
1807 return;
1808 }
1809
1810 const std::string& path = subtree[0].first;
1811 const std::string& service = subtree[0].second.begin()->first;
1812
1813 if (service.empty())
1814 {
1815 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1816 messages::internalError(aResp->res);
1817 return;
1818 }
1819
1820 crow::connections::systemBus->async_method_call(
1821 [aResp](const boost::system::error_code ec2) {
1822 if (ec2)
1823 {
1824 BMCWEB_LOG_DEBUG
1825 << "D-Bus response error on AssetTag Set " << ec2;
1826 messages::internalError(aResp->res);
1827 return;
1828 }
1829 },
1830 service, path, "org.freedesktop.DBus.Properties", "Set",
1831 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1832 std::variant<std::string>(assetTag));
1833 },
1834 "xyz.openbmc_project.ObjectMapper",
1835 "/xyz/openbmc_project/object_mapper",
1836 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1837 "/xyz/openbmc_project/inventory", int32_t(0),
1838 std::array<const char*, 1>{
1839 "xyz.openbmc_project.Inventory.Item.System"});
1840}
1841
1842/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001843 * @brief Sets automaticRetry (Auto Reboot)
1844 *
1845 * @param[in] aResp Shared pointer for generating response message.
1846 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1847 *
1848 * @return None.
1849 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001850inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001851 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001852{
1853 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1854
1855 // OpenBMC only supports "Disabled" and "RetryAttempts".
1856 bool autoRebootEnabled;
1857
1858 if (automaticRetryConfig == "Disabled")
1859 {
1860 autoRebootEnabled = false;
1861 }
1862 else if (automaticRetryConfig == "RetryAttempts")
1863 {
1864 autoRebootEnabled = true;
1865 }
1866 else
1867 {
George Liu0fda0f12021-11-16 10:06:17 +08001868 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001869 << automaticRetryConfig;
1870 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1871 "AutomaticRetryConfig");
1872 return;
1873 }
1874
1875 crow::connections::systemBus->async_method_call(
1876 [aResp](const boost::system::error_code ec) {
1877 if (ec)
1878 {
1879 messages::internalError(aResp->res);
1880 return;
1881 }
1882 },
1883 "xyz.openbmc_project.Settings",
1884 "/xyz/openbmc_project/control/host0/auto_reboot",
1885 "org.freedesktop.DBus.Properties", "Set",
1886 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1887 std::variant<bool>(autoRebootEnabled));
1888}
1889
1890/**
George Liuc6a620f2020-04-10 17:18:11 +08001891 * @brief Sets power restore policy properties.
1892 *
1893 * @param[in] aResp Shared pointer for generating response message.
1894 * @param[in] policy power restore policy properties from request.
1895 *
1896 * @return None.
1897 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001898inline void
1899 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1900 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001901{
1902 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1903
1904 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001905 {"AlwaysOn",
1906 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1907 {"AlwaysOff",
1908 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1909 {"LastState",
1910 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001911
1912 std::string powerRestorPolicy;
1913
Gunnar Mills4e69c902021-01-05 19:50:11 -06001914 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001915 if (policyMapsIt == policyMaps.end())
1916 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001917 messages::propertyValueNotInList(aResp->res, policy,
1918 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001919 return;
1920 }
1921
1922 powerRestorPolicy = policyMapsIt->second;
1923
1924 crow::connections::systemBus->async_method_call(
1925 [aResp](const boost::system::error_code ec) {
1926 if (ec)
1927 {
1928 messages::internalError(aResp->res);
1929 return;
1930 }
1931 },
1932 "xyz.openbmc_project.Settings",
1933 "/xyz/openbmc_project/control/host0/power_restore_policy",
1934 "org.freedesktop.DBus.Properties", "Set",
1935 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1936 std::variant<std::string>(powerRestorPolicy));
1937}
1938
AppaRao Pulia6349912019-10-18 17:16:08 +05301939#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1940/**
1941 * @brief Retrieves provisioning status
1942 *
1943 * @param[in] aResp Shared pointer for completing asynchronous calls.
1944 *
1945 * @return None.
1946 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001947inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301948{
1949 BMCWEB_LOG_DEBUG << "Get OEM information.";
1950 crow::connections::systemBus->async_method_call(
1951 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001952 const std::vector<std::pair<std::string, VariantType>>&
1953 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301954 nlohmann::json& oemPFR =
1955 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001956 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1957 "#OemComputerSystem.OpenBmc";
1958 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1959
AppaRao Pulia6349912019-10-18 17:16:08 +05301960 if (ec)
1961 {
1962 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301963 // not an error, don't have to have the interface
1964 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301965 return;
1966 }
1967
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001968 const bool* provState = nullptr;
1969 const bool* lockState = nullptr;
1970 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301971 propertiesList)
1972 {
1973 if (property.first == "UfmProvisioned")
1974 {
1975 provState = std::get_if<bool>(&property.second);
1976 }
1977 else if (property.first == "UfmLocked")
1978 {
1979 lockState = std::get_if<bool>(&property.second);
1980 }
1981 }
1982
1983 if ((provState == nullptr) || (lockState == nullptr))
1984 {
1985 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1986 messages::internalError(aResp->res);
1987 return;
1988 }
1989
AppaRao Pulia6349912019-10-18 17:16:08 +05301990 if (*provState == true)
1991 {
1992 if (*lockState == true)
1993 {
1994 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1995 }
1996 else
1997 {
1998 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1999 }
2000 }
2001 else
2002 {
2003 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2004 }
2005 },
2006 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2007 "org.freedesktop.DBus.Properties", "GetAll",
2008 "xyz.openbmc_project.PFR.Attributes");
2009}
2010#endif
2011
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302012/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002013 * @brief Translate the PowerMode to a response message.
2014 *
2015 * @param[in] aResp Shared pointer for generating response message.
2016 * @param[in] modeValue PowerMode value to be translated
2017 *
2018 * @return None.
2019 */
2020inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2021 const std::string& modeValue)
2022{
2023 std::string modeString;
2024
George Liu0fda0f12021-11-16 10:06:17 +08002025 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002026 {
2027 aResp->res.jsonValue["PowerMode"] = "Static";
2028 }
George Liu0fda0f12021-11-16 10:06:17 +08002029 else if (
2030 modeValue ==
2031 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002032 {
2033 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2034 }
George Liu0fda0f12021-11-16 10:06:17 +08002035 else if (modeValue ==
2036 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002037 {
2038 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2039 }
George Liu0fda0f12021-11-16 10:06:17 +08002040 else if (modeValue ==
2041 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002042 {
2043 aResp->res.jsonValue["PowerMode"] = "OEM";
2044 }
2045 else
2046 {
2047 // Any other values would be invalid
2048 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2049 messages::internalError(aResp->res);
2050 }
2051}
2052
2053/**
2054 * @brief Retrieves system power mode
2055 *
2056 * @param[in] aResp Shared pointer for generating response message.
2057 *
2058 * @return None.
2059 */
2060inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2061{
2062 BMCWEB_LOG_DEBUG << "Get power mode.";
2063
2064 // Get Power Mode object path:
2065 crow::connections::systemBus->async_method_call(
2066 [aResp](
2067 const boost::system::error_code ec,
2068 const std::vector<std::pair<
2069 std::string,
2070 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2071 subtree) {
2072 if (ec)
2073 {
2074 BMCWEB_LOG_DEBUG
2075 << "DBUS response error on Power.Mode GetSubTree " << ec;
2076 // This is an optional D-Bus object so just return if
2077 // error occurs
2078 return;
2079 }
2080 if (subtree.empty())
2081 {
2082 // As noted above, this is an optional interface so just return
2083 // if there is no instance found
2084 return;
2085 }
2086 if (subtree.size() > 1)
2087 {
2088 // More then one PowerMode object is not supported and is an
2089 // error
2090 BMCWEB_LOG_DEBUG
2091 << "Found more than 1 system D-Bus Power.Mode objects: "
2092 << subtree.size();
2093 messages::internalError(aResp->res);
2094 return;
2095 }
2096 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2097 {
2098 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2099 messages::internalError(aResp->res);
2100 return;
2101 }
2102 const std::string& path = subtree[0].first;
2103 const std::string& service = subtree[0].second.begin()->first;
2104 if (service.empty())
2105 {
2106 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2107 messages::internalError(aResp->res);
2108 return;
2109 }
2110 // Valid Power Mode object found, now read the current value
2111 crow::connections::systemBus->async_method_call(
2112 [aResp](const boost::system::error_code ec,
2113 const std::variant<std::string>& pmode) {
2114 if (ec)
2115 {
2116 BMCWEB_LOG_DEBUG
2117 << "DBUS response error on PowerMode Get: " << ec;
2118 messages::internalError(aResp->res);
2119 return;
2120 }
2121
2122 const std::string* s = std::get_if<std::string>(&pmode);
2123 if (s == nullptr)
2124 {
2125 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2126 messages::internalError(aResp->res);
2127 return;
2128 }
2129
2130 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2131 {"Static", "MaximumPerformance", "PowerSaving"};
2132
2133 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2134 translatePowerMode(aResp, *s);
2135 },
2136 service, path, "org.freedesktop.DBus.Properties", "Get",
2137 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2138 },
2139 "xyz.openbmc_project.ObjectMapper",
2140 "/xyz/openbmc_project/object_mapper",
2141 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2142 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2143}
2144
2145/**
2146 * @brief Validate the specified mode is valid and return the PowerMode
2147 * name associated with that string
2148 *
2149 * @param[in] aResp Shared pointer for generating response message.
2150 * @param[in] modeString String representing the desired PowerMode
2151 *
2152 * @return PowerMode value or empty string if mode is not valid
2153 */
2154inline std::string
2155 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2156 const std::string& modeString)
2157{
2158 std::string mode;
2159
2160 if (modeString == "Static")
2161 {
2162 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2163 }
2164 else if (modeString == "MaximumPerformance")
2165 {
George Liu0fda0f12021-11-16 10:06:17 +08002166 mode =
2167 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002168 }
2169 else if (modeString == "PowerSaving")
2170 {
2171 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2172 }
2173 else
2174 {
2175 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2176 }
2177 return mode;
2178}
2179
2180/**
2181 * @brief Sets system power mode.
2182 *
2183 * @param[in] aResp Shared pointer for generating response message.
2184 * @param[in] pmode System power mode from request.
2185 *
2186 * @return None.
2187 */
2188inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2189 const std::string& pmode)
2190{
2191 BMCWEB_LOG_DEBUG << "Set power mode.";
2192
2193 std::string powerMode = validatePowerMode(aResp, pmode);
2194 if (powerMode.empty())
2195 {
2196 return;
2197 }
2198
2199 // Get Power Mode object path:
2200 crow::connections::systemBus->async_method_call(
2201 [aResp, powerMode](
2202 const boost::system::error_code ec,
2203 const std::vector<std::pair<
2204 std::string,
2205 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2206 subtree) {
2207 if (ec)
2208 {
2209 BMCWEB_LOG_DEBUG
2210 << "DBUS response error on Power.Mode GetSubTree " << ec;
2211 // This is an optional D-Bus object, but user attempted to patch
2212 messages::internalError(aResp->res);
2213 return;
2214 }
2215 if (subtree.empty())
2216 {
2217 // This is an optional D-Bus object, but user attempted to patch
2218 messages::resourceNotFound(aResp->res, "ComputerSystem",
2219 "PowerMode");
2220 return;
2221 }
2222 if (subtree.size() > 1)
2223 {
2224 // More then one PowerMode object is not supported and is an
2225 // error
2226 BMCWEB_LOG_DEBUG
2227 << "Found more than 1 system D-Bus Power.Mode objects: "
2228 << subtree.size();
2229 messages::internalError(aResp->res);
2230 return;
2231 }
2232 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2233 {
2234 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2235 messages::internalError(aResp->res);
2236 return;
2237 }
2238 const std::string& path = subtree[0].first;
2239 const std::string& service = subtree[0].second.begin()->first;
2240 if (service.empty())
2241 {
2242 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2243 messages::internalError(aResp->res);
2244 return;
2245 }
2246
2247 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2248 << path;
2249
2250 // Set the Power Mode property
2251 crow::connections::systemBus->async_method_call(
2252 [aResp](const boost::system::error_code ec) {
2253 if (ec)
2254 {
2255 messages::internalError(aResp->res);
2256 return;
2257 }
2258 },
2259 service, path, "org.freedesktop.DBus.Properties", "Set",
2260 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2261 std::variant<std::string>(powerMode));
2262 },
2263 "xyz.openbmc_project.ObjectMapper",
2264 "/xyz/openbmc_project/object_mapper",
2265 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2266 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2267}
2268
2269/**
Yong Li51709ff2019-09-30 14:13:04 +08002270 * @brief Translates watchdog timeout action DBUS property value to redfish.
2271 *
2272 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2273 *
2274 * @return Returns as a string, the timeout action in Redfish terms. If
2275 * translation cannot be done, returns an empty string.
2276 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002277inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002278{
2279 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2280 {
2281 return "None";
2282 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002283 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002284 {
2285 return "ResetSystem";
2286 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002287 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002288 {
2289 return "PowerDown";
2290 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002291 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002292 {
2293 return "PowerCycle";
2294 }
2295
2296 return "";
2297}
2298
2299/**
Yong Lic45f0082019-10-10 14:19:01 +08002300 *@brief Translates timeout action from Redfish to DBUS property value.
2301 *
2302 *@param[in] rfAction The timeout action in Redfish.
2303 *
2304 *@return Returns as a string, the time_out action as expected by DBUS.
2305 *If translation cannot be done, returns an empty string.
2306 */
2307
Ed Tanous23a21a12020-07-25 04:45:05 +00002308inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002309{
2310 if (rfAction == "None")
2311 {
2312 return "xyz.openbmc_project.State.Watchdog.Action.None";
2313 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002314 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002315 {
2316 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2317 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002318 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002319 {
2320 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2321 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002322 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002323 {
2324 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2325 }
2326
2327 return "";
2328}
2329
2330/**
Yong Li51709ff2019-09-30 14:13:04 +08002331 * @brief Retrieves host watchdog timer properties over DBUS
2332 *
2333 * @param[in] aResp Shared pointer for completing asynchronous calls.
2334 *
2335 * @return None.
2336 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002337inline void
2338 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002339{
2340 BMCWEB_LOG_DEBUG << "Get host watchodg";
2341 crow::connections::systemBus->async_method_call(
2342 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002343 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002344 if (ec)
2345 {
2346 // watchdog service is stopped
2347 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2348 return;
2349 }
2350
2351 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2352
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002353 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002354 aResp->res.jsonValue["HostWatchdogTimer"];
2355
2356 // watchdog service is running/enabled
2357 hostWatchdogTimer["Status"]["State"] = "Enabled";
2358
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002359 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002360 {
2361 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2362 if (property.first == "Enabled")
2363 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002364 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002365
2366 if (!state)
2367 {
2368 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002369 return;
Yong Li51709ff2019-09-30 14:13:04 +08002370 }
2371
2372 hostWatchdogTimer["FunctionEnabled"] = *state;
2373 }
2374 else if (property.first == "ExpireAction")
2375 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002376 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002377 std::get_if<std::string>(&property.second);
2378 if (!s)
2379 {
2380 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002381 return;
Yong Li51709ff2019-09-30 14:13:04 +08002382 }
2383
2384 std::string action = dbusToRfWatchdogAction(*s);
2385 if (action.empty())
2386 {
2387 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002388 return;
Yong Li51709ff2019-09-30 14:13:04 +08002389 }
2390 hostWatchdogTimer["TimeoutAction"] = action;
2391 }
2392 }
2393 },
2394 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2395 "org.freedesktop.DBus.Properties", "GetAll",
2396 "xyz.openbmc_project.State.Watchdog");
2397}
2398
2399/**
Yong Lic45f0082019-10-10 14:19:01 +08002400 * @brief Sets Host WatchDog Timer properties.
2401 *
2402 * @param[in] aResp Shared pointer for generating response message.
2403 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2404 * RF request.
2405 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2406 *
2407 * @return None.
2408 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002409inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002410 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002411 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002412{
2413 BMCWEB_LOG_DEBUG << "Set host watchdog";
2414
2415 if (wdtTimeOutAction)
2416 {
2417 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2418 // check if TimeOut Action is Valid
2419 if (wdtTimeOutActStr.empty())
2420 {
2421 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2422 << *wdtTimeOutAction;
2423 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2424 "TimeoutAction");
2425 return;
2426 }
2427
2428 crow::connections::systemBus->async_method_call(
2429 [aResp](const boost::system::error_code ec) {
2430 if (ec)
2431 {
2432 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2433 messages::internalError(aResp->res);
2434 return;
2435 }
2436 },
2437 "xyz.openbmc_project.Watchdog",
2438 "/xyz/openbmc_project/watchdog/host0",
2439 "org.freedesktop.DBus.Properties", "Set",
2440 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2441 std::variant<std::string>(wdtTimeOutActStr));
2442 }
2443
2444 if (wdtEnable)
2445 {
2446 crow::connections::systemBus->async_method_call(
2447 [aResp](const boost::system::error_code ec) {
2448 if (ec)
2449 {
2450 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2451 messages::internalError(aResp->res);
2452 return;
2453 }
2454 },
2455 "xyz.openbmc_project.Watchdog",
2456 "/xyz/openbmc_project/watchdog/host0",
2457 "org.freedesktop.DBus.Properties", "Set",
2458 "xyz.openbmc_project.State.Watchdog", "Enabled",
2459 std::variant<bool>(*wdtEnable));
2460 }
2461}
2462
Chris Cain37bbf982021-09-20 10:53:09 -05002463using ipsPropertiesType =
2464 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2465/**
2466 * @brief Parse the Idle Power Saver properties into json
2467 *
2468 * @param[in] aResp Shared pointer for completing asynchronous calls.
2469 * @param[in] properties IPS property data from DBus.
2470 *
2471 * @return true if successful
2472 */
Ed Tanousf6674222021-11-13 09:41:41 -08002473inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2474 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002475{
2476 for (const auto& property : properties)
2477 {
2478 if (property.first == "Enabled")
2479 {
2480 const bool* state = std::get_if<bool>(&property.second);
2481 if (!state)
2482 {
2483 return false;
2484 }
2485 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2486 }
2487 else if (property.first == "EnterUtilizationPercent")
2488 {
2489 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2490 if (!util)
2491 {
2492 return false;
2493 }
2494 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2495 }
2496 else if (property.first == "EnterDwellTime")
2497 {
2498 // Convert Dbus time from milliseconds to seconds
2499 const uint64_t* timeMilliseconds =
2500 std::get_if<uint64_t>(&property.second);
2501 if (!timeMilliseconds)
2502 {
2503 return false;
2504 }
2505 const std::chrono::duration<uint64_t, std::milli> ms(
2506 *timeMilliseconds);
2507 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2508 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2509 .count();
2510 }
2511 else if (property.first == "ExitUtilizationPercent")
2512 {
2513 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2514 if (!util)
2515 {
2516 return false;
2517 }
2518 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2519 }
2520 else if (property.first == "ExitDwellTime")
2521 {
2522 // Convert Dbus time from milliseconds to seconds
2523 const uint64_t* timeMilliseconds =
2524 std::get_if<uint64_t>(&property.second);
2525 if (!timeMilliseconds)
2526 {
2527 return false;
2528 }
2529 const std::chrono::duration<uint64_t, std::milli> ms(
2530 *timeMilliseconds);
2531 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2532 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2533 .count();
2534 }
2535 else
2536 {
2537 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2538 << property.first;
2539 }
2540 }
2541
2542 return true;
2543}
2544
2545/**
2546 * @brief Retrieves host watchdog timer properties over DBUS
2547 *
2548 * @param[in] aResp Shared pointer for completing asynchronous calls.
2549 *
2550 * @return None.
2551 */
2552inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2553{
2554 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2555
2556 // Get IdlePowerSaver object path:
2557 crow::connections::systemBus->async_method_call(
2558 [aResp](
2559 const boost::system::error_code ec,
2560 const std::vector<std::pair<
2561 std::string,
2562 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2563 subtree) {
2564 if (ec)
2565 {
2566 BMCWEB_LOG_DEBUG
2567 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2568 << ec;
2569 messages::internalError(aResp->res);
2570 return;
2571 }
2572 if (subtree.empty())
2573 {
2574 // This is an optional interface so just return
2575 // if there is no instance found
2576 BMCWEB_LOG_DEBUG << "No instances found";
2577 return;
2578 }
2579 if (subtree.size() > 1)
2580 {
2581 // More then one PowerIdlePowerSaver object is not supported and
2582 // is an error
2583 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2584 "Power.IdlePowerSaver objects: "
2585 << subtree.size();
2586 messages::internalError(aResp->res);
2587 return;
2588 }
2589 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2590 {
2591 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2592 messages::internalError(aResp->res);
2593 return;
2594 }
2595 const std::string& path = subtree[0].first;
2596 const std::string& service = subtree[0].second.begin()->first;
2597 if (service.empty())
2598 {
2599 BMCWEB_LOG_DEBUG
2600 << "Power.IdlePowerSaver service mapper error!";
2601 messages::internalError(aResp->res);
2602 return;
2603 }
2604
2605 // Valid IdlePowerSaver object found, now read the current values
2606 crow::connections::systemBus->async_method_call(
2607 [aResp](const boost::system::error_code ec,
2608 ipsPropertiesType& properties) {
2609 if (ec)
2610 {
2611 BMCWEB_LOG_ERROR
2612 << "DBUS response error on IdlePowerSaver GetAll: "
2613 << ec;
2614 messages::internalError(aResp->res);
2615 return;
2616 }
2617
2618 if (parseIpsProperties(aResp, properties) == false)
2619 {
2620 messages::internalError(aResp->res);
2621 return;
2622 }
2623 },
2624 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2625 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2626 },
2627 "xyz.openbmc_project.ObjectMapper",
2628 "/xyz/openbmc_project/object_mapper",
2629 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2630 std::array<const char*, 1>{
2631 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2632
2633 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2634}
2635
2636/**
2637 * @brief Sets Idle Power Saver properties.
2638 *
2639 * @param[in] aResp Shared pointer for generating response message.
2640 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2641 * RF request.
2642 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2643 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2644 * before entering idle state.
2645 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2646 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2647 * before exiting idle state
2648 *
2649 * @return None.
2650 */
2651inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2652 const std::optional<bool> ipsEnable,
2653 const std::optional<uint8_t> ipsEnterUtil,
2654 const std::optional<uint64_t> ipsEnterTime,
2655 const std::optional<uint8_t> ipsExitUtil,
2656 const std::optional<uint64_t> ipsExitTime)
2657{
2658 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2659
2660 // Get IdlePowerSaver object path:
2661 crow::connections::systemBus->async_method_call(
2662 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2663 ipsExitTime](
2664 const boost::system::error_code ec,
2665 const std::vector<std::pair<
2666 std::string,
2667 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2668 subtree) {
2669 if (ec)
2670 {
2671 BMCWEB_LOG_DEBUG
2672 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2673 << ec;
2674 messages::internalError(aResp->res);
2675 return;
2676 }
2677 if (subtree.empty())
2678 {
2679 // This is an optional D-Bus object, but user attempted to patch
2680 messages::resourceNotFound(aResp->res, "ComputerSystem",
2681 "IdlePowerSaver");
2682 return;
2683 }
2684 if (subtree.size() > 1)
2685 {
2686 // More then one PowerIdlePowerSaver object is not supported and
2687 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002688 BMCWEB_LOG_DEBUG
2689 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2690 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002691 messages::internalError(aResp->res);
2692 return;
2693 }
2694 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2695 {
2696 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2697 messages::internalError(aResp->res);
2698 return;
2699 }
2700 const std::string& path = subtree[0].first;
2701 const std::string& service = subtree[0].second.begin()->first;
2702 if (service.empty())
2703 {
2704 BMCWEB_LOG_DEBUG
2705 << "Power.IdlePowerSaver service mapper error!";
2706 messages::internalError(aResp->res);
2707 return;
2708 }
2709
2710 // Valid Power IdlePowerSaver object found, now set any values that
2711 // need to be updated
2712
2713 if (ipsEnable)
2714 {
2715 crow::connections::systemBus->async_method_call(
2716 [aResp](const boost::system::error_code ec) {
2717 if (ec)
2718 {
2719 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2720 messages::internalError(aResp->res);
2721 return;
2722 }
2723 },
2724 service, path, "org.freedesktop.DBus.Properties", "Set",
2725 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2726 "Enabled", std::variant<bool>(*ipsEnable));
2727 }
2728 if (ipsEnterUtil)
2729 {
2730 crow::connections::systemBus->async_method_call(
2731 [aResp](const boost::system::error_code ec) {
2732 if (ec)
2733 {
2734 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2735 messages::internalError(aResp->res);
2736 return;
2737 }
2738 },
2739 service, path, "org.freedesktop.DBus.Properties", "Set",
2740 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2741 "EnterUtilizationPercent",
2742 std::variant<uint8_t>(*ipsEnterUtil));
2743 }
2744 if (ipsEnterTime)
2745 {
2746 // Convert from seconds into milliseconds for DBus
2747 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2748 crow::connections::systemBus->async_method_call(
2749 [aResp](const boost::system::error_code ec) {
2750 if (ec)
2751 {
2752 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2753 messages::internalError(aResp->res);
2754 return;
2755 }
2756 },
2757 service, path, "org.freedesktop.DBus.Properties", "Set",
2758 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2759 "EnterDwellTime", std::variant<uint64_t>(timeMilliseconds));
2760 }
2761 if (ipsExitUtil)
2762 {
2763 crow::connections::systemBus->async_method_call(
2764 [aResp](const boost::system::error_code ec) {
2765 if (ec)
2766 {
2767 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2768 messages::internalError(aResp->res);
2769 return;
2770 }
2771 },
2772 service, path, "org.freedesktop.DBus.Properties", "Set",
2773 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2774 "ExitUtilizationPercent",
2775 std::variant<uint8_t>(*ipsExitUtil));
2776 }
2777 if (ipsExitTime)
2778 {
2779 // Convert from seconds into milliseconds for DBus
2780 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2781 crow::connections::systemBus->async_method_call(
2782 [aResp](const boost::system::error_code ec) {
2783 if (ec)
2784 {
2785 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2786 messages::internalError(aResp->res);
2787 return;
2788 }
2789 },
2790 service, path, "org.freedesktop.DBus.Properties", "Set",
2791 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2792 "ExitDwellTime", std::variant<uint64_t>(timeMilliseconds));
2793 }
2794 },
2795 "xyz.openbmc_project.ObjectMapper",
2796 "/xyz/openbmc_project/object_mapper",
2797 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2798 std::array<const char*, 1>{
2799 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2800
2801 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2802}
2803
Yong Lic45f0082019-10-10 14:19:01 +08002804/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002805 * SystemsCollection derived class for delivering ComputerSystems Collection
2806 * Schema
2807 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002808inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002809{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002810 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002811 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002812 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002813 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002814 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2815 asyncResp->res.jsonValue["@odata.type"] =
2816 "#ComputerSystemCollection.ComputerSystemCollection";
2817 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2818 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002819
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002820 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002821 [asyncResp](const boost::system::error_code ec,
2822 const std::variant<std::string>& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002823 nlohmann::json& ifaceArray =
2824 asyncResp->res.jsonValue["Members"];
2825 ifaceArray = nlohmann::json::array();
2826 auto& count =
2827 asyncResp->res.jsonValue["Members@odata.count"];
2828 ifaceArray.push_back(
2829 {{"@odata.id", "/redfish/v1/Systems/system"}});
2830 count = ifaceArray.size();
2831 if (!ec)
2832 {
2833 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2834 ifaceArray.push_back(
2835 {{"@odata.id",
2836 "/redfish/v1/Systems/hypervisor"}});
2837 count = ifaceArray.size();
2838 }
2839 },
2840 "xyz.openbmc_project.Settings",
2841 "/xyz/openbmc_project/network/hypervisor",
2842 "org.freedesktop.DBus.Properties", "Get",
2843 "xyz.openbmc_project.Network.SystemConfiguration",
2844 "HostName");
2845 });
2846}
Sunitha Harish462023a2020-02-19 08:34:59 -06002847
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002848/**
2849 * Function transceives data with dbus directly.
2850 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002851inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002852{
2853 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2854 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2855 constexpr char const* interfaceName =
2856 "xyz.openbmc_project.Control.Host.NMI";
2857 constexpr char const* method = "NMI";
2858
2859 crow::connections::systemBus->async_method_call(
2860 [asyncResp](const boost::system::error_code ec) {
2861 if (ec)
2862 {
2863 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2864 messages::internalError(asyncResp->res);
2865 return;
2866 }
2867 messages::success(asyncResp->res);
2868 },
2869 serviceName, objectPath, interfaceName, method);
2870}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002871
2872/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002873 * SystemActionsReset class supports handle POST method for Reset action.
2874 * The class retrieves and sends data directly to D-Bus.
2875 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002876inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002877{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002878 /**
2879 * Function handles POST method request.
2880 * Analyzes POST body message before sends Reset request data to D-Bus.
2881 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882 BMCWEB_ROUTE(app,
2883 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002884 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002885 .methods(
2886 boost::beast::http::verb::
2887 post)([](const crow::Request& req,
2888 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2889 std::string resetType;
2890 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2891 resetType))
2892 {
2893 return;
2894 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002895
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002896 // Get the command and host vs. chassis
2897 std::string command;
2898 bool hostCommand;
2899 if ((resetType == "On") || (resetType == "ForceOn"))
2900 {
2901 command = "xyz.openbmc_project.State.Host.Transition.On";
2902 hostCommand = true;
2903 }
2904 else if (resetType == "ForceOff")
2905 {
2906 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2907 hostCommand = false;
2908 }
2909 else if (resetType == "ForceRestart")
2910 {
2911 command =
2912 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2913 hostCommand = true;
2914 }
2915 else if (resetType == "GracefulShutdown")
2916 {
2917 command = "xyz.openbmc_project.State.Host.Transition.Off";
2918 hostCommand = true;
2919 }
2920 else if (resetType == "GracefulRestart")
2921 {
George Liu0fda0f12021-11-16 10:06:17 +08002922 command =
2923 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002924 hostCommand = true;
2925 }
2926 else if (resetType == "PowerCycle")
2927 {
2928 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2929 hostCommand = true;
2930 }
2931 else if (resetType == "Nmi")
2932 {
2933 doNMI(asyncResp);
2934 return;
2935 }
2936 else
2937 {
2938 messages::actionParameterUnknown(asyncResp->res, "Reset",
2939 resetType);
2940 return;
2941 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002942
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002943 if (hostCommand)
2944 {
2945 crow::connections::systemBus->async_method_call(
2946 [asyncResp, resetType](const boost::system::error_code ec) {
2947 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002948 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002949 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2950 if (ec.value() ==
2951 boost::asio::error::invalid_argument)
2952 {
2953 messages::actionParameterNotSupported(
2954 asyncResp->res, resetType, "Reset");
2955 }
2956 else
2957 {
2958 messages::internalError(asyncResp->res);
2959 }
2960 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002961 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002962 messages::success(asyncResp->res);
2963 },
2964 "xyz.openbmc_project.State.Host",
2965 "/xyz/openbmc_project/state/host0",
2966 "org.freedesktop.DBus.Properties", "Set",
2967 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2968 std::variant<std::string>{command});
2969 }
2970 else
2971 {
2972 crow::connections::systemBus->async_method_call(
2973 [asyncResp, resetType](const boost::system::error_code ec) {
2974 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002975 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002976 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2977 if (ec.value() ==
2978 boost::asio::error::invalid_argument)
2979 {
2980 messages::actionParameterNotSupported(
2981 asyncResp->res, resetType, "Reset");
2982 }
2983 else
2984 {
2985 messages::internalError(asyncResp->res);
2986 }
2987 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002988 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002989 messages::success(asyncResp->res);
2990 },
2991 "xyz.openbmc_project.State.Chassis",
2992 "/xyz/openbmc_project/state/chassis0",
2993 "org.freedesktop.DBus.Properties", "Set",
2994 "xyz.openbmc_project.State.Chassis",
2995 "RequestedPowerTransition",
2996 std::variant<std::string>{command});
2997 }
2998 });
2999}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003000
3001/**
Ed Tanous66173382018-08-15 18:20:59 -07003002 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003003 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003004inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003005{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003006
Ed Tanous1abe55e2018-09-05 08:30:59 -07003007 /**
3008 * Functions triggers appropriate requests on DBus
3009 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003010 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003011 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003012 .methods(
3013 boost::beast::http::verb::
3014 get)([](const crow::Request&,
3015 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3016 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05003017 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003018 asyncResp->res.jsonValue["Name"] = "system";
3019 asyncResp->res.jsonValue["Id"] = "system";
3020 asyncResp->res.jsonValue["SystemType"] = "Physical";
3021 asyncResp->res.jsonValue["Description"] = "Computer System";
3022 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3023 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3024 "Disabled";
3025 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3026 uint64_t(0);
3027 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3028 "Disabled";
3029 asyncResp->res.jsonValue["@odata.id"] =
3030 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003031
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003032 asyncResp->res.jsonValue["Processors"] = {
3033 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
3034 asyncResp->res.jsonValue["Memory"] = {
3035 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
3036 asyncResp->res.jsonValue["Storage"] = {
3037 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08003038
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
3040 {"target",
3041 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
3042 {"@Redfish.ActionInfo",
3043 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003044
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003045 asyncResp->res.jsonValue["LogServices"] = {
3046 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003047
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003048 asyncResp->res.jsonValue["Bios"] = {
3049 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08003050
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003051 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
3052 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08003053
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003054 asyncResp->res.jsonValue["Status"] = {
3055 {"Health", "OK"},
3056 {"State", "Enabled"},
3057 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003058
3059 // Fill in SerialConsole info
3060 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
3061 15;
3062 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
3063 {"ServiceEnabled", true},
3064 };
3065 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3066 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
3067 {"ServiceEnabled", true},
3068 {"Port", 2200},
3069 // https://github.com/openbmc/docs/blob/master/console.md
3070 {"HotKeySequenceDisplay", "Press ~. to exit console"},
3071 };
3072
3073#ifdef BMCWEB_ENABLE_KVM
3074 // Fill in GraphicalConsole info
3075 asyncResp->res.jsonValue["GraphicalConsole"] = {
3076 {"ServiceEnabled", true},
3077 {"MaxConcurrentSessions", 4},
3078 {"ConnectTypesSupported", {"KVMIP"}},
3079 };
3080#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003081 constexpr const std::array<const char*, 4> inventoryForSystems = {
3082 "xyz.openbmc_project.Inventory.Item.Dimm",
3083 "xyz.openbmc_project.Inventory.Item.Cpu",
3084 "xyz.openbmc_project.Inventory.Item.Drive",
3085 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003086
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003087 auto health = std::make_shared<HealthPopulate>(asyncResp);
3088 crow::connections::systemBus->async_method_call(
3089 [health](const boost::system::error_code ec,
3090 std::vector<std::string>& resp) {
3091 if (ec)
3092 {
3093 // no inventory
3094 return;
3095 }
3096
3097 health->inventory = std::move(resp);
3098 },
3099 "xyz.openbmc_project.ObjectMapper",
3100 "/xyz/openbmc_project/object_mapper",
3101 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
3102 int32_t(0), inventoryForSystems);
3103
3104 health->populate();
3105
3106 getMainChassisId(
3107 asyncResp, [](const std::string& chassisId,
3108 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3109 aRsp->res.jsonValue["Links"]["Chassis"] = {
3110 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
3111 });
3112
3113 getLocationIndicatorActive(asyncResp);
3114 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3115 getIndicatorLedState(asyncResp);
3116 getComputerSystem(asyncResp, health);
3117 getHostState(asyncResp);
3118 getBootProperties(asyncResp);
3119 getBootProgress(asyncResp);
3120 getPCIeDeviceList(asyncResp, "PCIeDevices");
3121 getHostWatchdogTimer(asyncResp);
3122 getPowerRestorePolicy(asyncResp);
3123 getAutomaticRetry(asyncResp);
3124 getLastResetTime(asyncResp);
3125#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
3126 getProvisioningStatus(asyncResp);
3127#endif
Ali Ahmed19817712021-06-29 17:01:52 -05003128 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05003129 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003130 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003131 });
3132 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003133 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003134 .methods(boost::beast::http::verb::patch)(
3135 [](const crow::Request& req,
3136 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3137 std::optional<bool> locationIndicatorActive;
3138 std::optional<std::string> indicatorLed;
3139 std::optional<nlohmann::json> bootProps;
3140 std::optional<nlohmann::json> wdtTimerProps;
3141 std::optional<std::string> assetTag;
3142 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003143 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003144 std::optional<nlohmann::json> ipsProps;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003145 if (!json_util::readJson(
3146 req, asyncResp->res, "IndicatorLED", indicatorLed,
3147 "LocationIndicatorActive", locationIndicatorActive,
3148 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3149 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003150 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3151 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003152 {
James Feistb49ac872019-05-21 15:12:01 -07003153 return;
3154 }
3155
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003156 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003157
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003158 if (assetTag)
3159 {
3160 setAssetTag(asyncResp, *assetTag);
3161 }
James Feistb49ac872019-05-21 15:12:01 -07003162
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003163 if (wdtTimerProps)
3164 {
3165 std::optional<bool> wdtEnable;
3166 std::optional<std::string> wdtTimeOutAction;
3167
3168 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3169 "FunctionEnabled", wdtEnable,
3170 "TimeoutAction", wdtTimeOutAction))
3171 {
3172 return;
3173 }
3174 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3175 }
3176
3177 if (bootProps)
3178 {
3179 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003180 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003181 std::optional<std::string> bootEnable;
3182 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003183 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003184
3185 if (!json_util::readJson(
3186 *bootProps, asyncResp->res,
3187 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003188 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003189 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003190 "AutomaticRetryConfig", automaticRetryConfig,
3191 "TrustedModuleRequiredToBoot",
3192 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003193 {
3194 return;
3195 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003196
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003197 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003198 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003199 setBootProperties(asyncResp, bootSource, bootType,
3200 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003201 }
3202 if (automaticRetryConfig)
3203 {
3204 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3205 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003206
3207 if (trustedModuleRequiredToBoot)
3208 {
3209 setTrustedModuleRequiredToBoot(
3210 asyncResp, *trustedModuleRequiredToBoot);
3211 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003212 }
3213
3214 if (locationIndicatorActive)
3215 {
3216 setLocationIndicatorActive(asyncResp,
3217 *locationIndicatorActive);
3218 }
3219
3220 // TODO (Gunnar): Remove IndicatorLED after enough time has
3221 // passed
3222 if (indicatorLed)
3223 {
3224 setIndicatorLedState(asyncResp, *indicatorLed);
3225 asyncResp->res.addHeader(
3226 boost::beast::http::field::warning,
3227 "299 - \"IndicatorLED is deprecated. Use "
3228 "LocationIndicatorActive instead.\"");
3229 }
3230
3231 if (powerRestorePolicy)
3232 {
3233 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3234 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003235
3236 if (powerMode)
3237 {
3238 setPowerMode(asyncResp, *powerMode);
3239 }
Chris Cain37bbf982021-09-20 10:53:09 -05003240
3241 if (ipsProps)
3242 {
3243 std::optional<bool> ipsEnable;
3244 std::optional<uint8_t> ipsEnterUtil;
3245 std::optional<uint64_t> ipsEnterTime;
3246 std::optional<uint8_t> ipsExitUtil;
3247 std::optional<uint64_t> ipsExitTime;
3248
3249 if (!json_util::readJson(
3250 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3251 "EnterUtilizationPercent", ipsEnterUtil,
3252 "EnterDwellTimeSeconds", ipsEnterTime,
3253 "ExitUtilizationPercent", ipsExitUtil,
3254 "ExitDwellTimeSeconds", ipsExitTime))
3255 {
3256 return;
3257 }
3258 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3259 ipsEnterTime, ipsExitUtil, ipsExitTime);
3260 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003261 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003262}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303263
3264/**
3265 * SystemResetActionInfo derived class for delivering Computer Systems
3266 * ResetType AllowableValues using ResetInfo schema.
3267 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003268inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303269{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303270
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303271 /**
3272 * Functions triggers appropriate requests on DBus
3273 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003274 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003275 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003276 .methods(boost::beast::http::verb::get)(
3277 [](const crow::Request&,
3278 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3279 asyncResp->res.jsonValue = {
3280 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3281 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3282 {"Name", "Reset Action Info"},
3283 {"Id", "ResetActionInfo"},
3284 {"Parameters",
3285 {{{"Name", "ResetType"},
3286 {"Required", true},
3287 {"DataType", "String"},
3288 {"AllowableValues",
3289 {"On", "ForceOff", "ForceOn", "ForceRestart",
3290 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3291 "Nmi"}}}}}};
3292 });
3293}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003294} // namespace redfish