blob: 680a0ee7dbb6eaeec72c8dafe284a693ec2b3718 [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
142/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700143 * @brief Retrieves computer system properties over dbus
144 *
145 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500146 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700147 *
148 * @return None.
149 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700150inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800151 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700152 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700153{
Ed Tanous6c34de42018-08-29 13:37:36 -0700154 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500155
Ed Tanous6c34de42018-08-29 13:37:36 -0700156 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700157 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700158 const boost::system::error_code ec,
159 const std::vector<std::pair<
160 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500161 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
162 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700163 if (ec)
164 {
165 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700166 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700167 return;
168 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700169 // Iterate over all retrieved ObjectPaths.
170 for (const std::pair<std::string,
171 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500172 std::string, std::vector<std::string>>>>&
173 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700174 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500175 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700176 BMCWEB_LOG_DEBUG << "Got path: " << path;
177 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500178 std::pair<std::string, std::vector<std::string>>>&
179 connectionNames = object.second;
Ed Tanous6c34de42018-08-29 13:37:36 -0700180 if (connectionNames.size() < 1)
181 {
182 continue;
183 }
Ed Tanous029573d2019-02-01 10:57:49 -0800184
James Feist5bc2dc82019-10-22 14:33:16 -0700185 auto memoryHealth = std::make_shared<HealthPopulate>(
186 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
187
188 auto cpuHealth = std::make_shared<HealthPopulate>(
189 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
190
191 systemHealth->children.emplace_back(memoryHealth);
192 systemHealth->children.emplace_back(cpuHealth);
193
Ed Tanous029573d2019-02-01 10:57:49 -0800194 // This is not system, so check if it's cpu, dimm, UUID or
195 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500196 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700197 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500198 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700199 {
Ed Tanous029573d2019-02-01 10:57:49 -0800200 if (interfaceName ==
201 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700202 {
Ed Tanous029573d2019-02-01 10:57:49 -0800203 BMCWEB_LOG_DEBUG
204 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500205
Ed Tanous029573d2019-02-01 10:57:49 -0800206 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500207 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700208 path](const boost::system::error_code ec2,
209 const std::vector<
210 std::pair<std::string, VariantType>>&
211 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000212 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800213 {
214 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000215 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800216 messages::internalError(aResp->res);
217 return;
218 }
219 BMCWEB_LOG_DEBUG << "Got "
220 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500221 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500222
223 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800224 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500225 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500226 VariantType>&
227 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700228 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800229 if (property.first !=
230 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700231 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800232 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700233 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500234 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500235 std::get_if<uint32_t>(
236 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800237 if (value == nullptr)
238 {
239 BMCWEB_LOG_DEBUG
240 << "Find incorrect type of "
241 "MemorySize";
242 continue;
243 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500244 nlohmann::json& totalMemory =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800245 aResp->res
246 .jsonValue["MemorySummar"
247 "y"]
248 ["TotalSystemMe"
249 "moryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500250 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800251 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500252 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800253 if (preValue == nullptr)
254 {
255 continue;
256 }
257 aResp->res
258 .jsonValue["MemorySummary"]
259 ["TotalSystemMemoryGi"
260 "B"] =
261 *value / (1024 * 1024) +
262 *preValue;
263 aResp->res
264 .jsonValue["MemorySummary"]
265 ["Status"]["State"] =
266 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700267 }
Ed Tanous029573d2019-02-01 10:57:49 -0800268 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500269 else
270 {
271 auto getDimmProperties =
272 [aResp](
273 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000274 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500275 const std::variant<bool>&
276 dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000277 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500278 {
279 BMCWEB_LOG_ERROR
280 << "DBUS response "
281 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000282 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500283 return;
284 }
285 updateDimmProperties(aResp,
286 dimmState);
287 };
288 crow::connections::systemBus
289 ->async_method_call(
290 std::move(getDimmProperties),
291 service, path,
292 "org.freedesktop.DBus."
293 "Properties",
294 "Get",
295 "xyz.openbmc_project.State."
296 "Decorator.OperationalStatus",
297 "Functional");
298 }
Ed Tanous029573d2019-02-01 10:57:49 -0800299 },
300 connection.first, path,
301 "org.freedesktop.DBus.Properties", "GetAll",
302 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700303
304 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800305 }
306 else if (interfaceName ==
307 "xyz.openbmc_project.Inventory.Item.Cpu")
308 {
309 BMCWEB_LOG_DEBUG
310 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500311
Ed Tanous029573d2019-02-01 10:57:49 -0800312 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500313 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700314 path](const boost::system::error_code ec2,
315 const std::vector<
316 std::pair<std::string, VariantType>>&
317 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000318 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800319 {
320 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000321 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800322 messages::internalError(aResp->res);
323 return;
324 }
325 BMCWEB_LOG_DEBUG << "Got "
326 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500327 << " Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700328
Ali Ahmeda1978342021-08-31 14:59:58 -0500329 auto getCpuPresenceState =
330 [aResp](
331 const boost::system::error_code ec3,
332 const std::variant<bool>&
333 cpuPresenceCheck) {
334 if (ec3)
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700335 {
Ali Ahmeda1978342021-08-31 14:59:58 -0500336 BMCWEB_LOG_ERROR
337 << "DBUS response error "
338 << ec3;
339 return;
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700340 }
Ali Ahmeda1978342021-08-31 14:59:58 -0500341 modifyCpuPresenceState(
342 aResp, cpuPresenceCheck);
343 };
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700344
Ali Ahmeda1978342021-08-31 14:59:58 -0500345 auto getCpuFunctionalState =
346 [aResp](
347 const boost::system::error_code ec3,
348 const std::variant<bool>&
349 cpuFunctionalCheck) {
350 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500351 {
Ali Ahmeda1978342021-08-31 14:59:58 -0500352 BMCWEB_LOG_ERROR
353 << "DBUS response error "
354 << ec3;
355 return;
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700356 }
Ali Ahmeda1978342021-08-31 14:59:58 -0500357 modifyCpuFunctionalState(
358 aResp, cpuFunctionalCheck);
359 };
James Feistb4b95952019-12-05 15:01:55 -0800360
Ali Ahmeda1978342021-08-31 14:59:58 -0500361 // Get the Presence of CPU
362 crow::connections::systemBus
363 ->async_method_call(
364 std::move(getCpuPresenceState),
365 service, path,
366 "org.freedesktop.DBus."
367 "Properties",
368 "Get",
369 "xyz.openbmc_project.Inventory."
370 "Item",
371 "Present");
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700372
Ali Ahmeda1978342021-08-31 14:59:58 -0500373 // Get the Functional State
374 crow::connections::systemBus
375 ->async_method_call(
376 std::move(getCpuFunctionalState),
377 service, path,
378 "org.freedesktop.DBus."
379 "Properties",
380 "Get",
381 "xyz.openbmc_project.State."
382 "Decorator."
383 "OperationalStatus",
384 "Functional");
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500385
Ali Ahmeda1978342021-08-31 14:59:58 -0500386 // Get the MODEL from
387 // xyz.openbmc_project.Inventory.Decorator.Asset
388 // support it later as Model is Empty
389 // currently.
Ed Tanous029573d2019-02-01 10:57:49 -0800390 },
391 connection.first, path,
392 "org.freedesktop.DBus.Properties", "GetAll",
393 "xyz.openbmc_project.Inventory.Item.Cpu");
James Feist5bc2dc82019-10-22 14:33:16 -0700394
395 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800396 }
397 else if (interfaceName ==
398 "xyz.openbmc_project.Common.UUID")
399 {
400 BMCWEB_LOG_DEBUG
401 << "Found UUID, now get its properties.";
402 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500403 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000404 const boost::system::error_code ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500405 const std::vector<
406 std::pair<std::string, VariantType>>&
407 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000408 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800409 {
410 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000411 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800412 messages::internalError(aResp->res);
413 return;
414 }
415 BMCWEB_LOG_DEBUG << "Got "
416 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500417 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800418 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500419 VariantType>&
420 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800421 {
Ed Tanous029573d2019-02-01 10:57:49 -0800422 if (property.first == "UUID")
423 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500424 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500425 std::get_if<std::string>(
426 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700427
Ed Tanous029573d2019-02-01 10:57:49 -0800428 if (value != nullptr)
429 {
430 std::string valueStr = *value;
431 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700432 {
Ed Tanous029573d2019-02-01 10:57:49 -0800433 valueStr.insert(8, 1, '-');
434 valueStr.insert(13, 1, '-');
435 valueStr.insert(18, 1, '-');
436 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700437 }
Ed Tanous029573d2019-02-01 10:57:49 -0800438 BMCWEB_LOG_DEBUG << "UUID = "
439 << valueStr;
440 aResp->res.jsonValue["UUID"] =
441 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700442 }
443 }
Ed Tanous029573d2019-02-01 10:57:49 -0800444 }
445 },
446 connection.first, path,
447 "org.freedesktop.DBus.Properties", "GetAll",
448 "xyz.openbmc_project.Common.UUID");
449 }
450 else if (interfaceName ==
451 "xyz.openbmc_project.Inventory.Item.System")
452 {
453 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500454 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000455 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500456 const std::vector<
457 std::pair<std::string, VariantType>>&
458 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000459 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800460 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700461 // doesn't have to include this
462 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800463 return;
464 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500465 BMCWEB_LOG_DEBUG
466 << "Got " << propertiesList.size()
467 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800468 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500469 VariantType>&
470 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800471 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500472 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600473 property.first;
474 if ((propertyName == "PartNumber") ||
475 (propertyName == "SerialNumber") ||
476 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500477 (propertyName == "Model") ||
478 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800479 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500480 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600481 std::get_if<std::string>(
482 &property.second);
483 if (value != nullptr)
484 {
485 aResp->res
486 .jsonValue[propertyName] =
487 *value;
488 }
Ed Tanous029573d2019-02-01 10:57:49 -0800489 }
490 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500491
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600492 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500493 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600494 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500495 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800496 },
497 connection.first, path,
498 "org.freedesktop.DBus.Properties", "GetAll",
499 "xyz.openbmc_project.Inventory.Decorator."
500 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700501
502 crow::connections::systemBus->async_method_call(
503 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000504 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500505 const std::variant<std::string>& property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000506 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700507 {
508 // doesn't have to include this
509 // interface
510 return;
511 }
512
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500513 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700514 std::get_if<std::string>(&property);
515 if (value != nullptr)
516 {
517 aResp->res.jsonValue["AssetTag"] =
518 *value;
519 }
520 },
521 connection.first, path,
522 "org.freedesktop.DBus.Properties", "Get",
523 "xyz.openbmc_project.Inventory.Decorator."
524 "AssetTag",
525 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700526 }
527 }
528 }
529 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700530 },
531 "xyz.openbmc_project.ObjectMapper",
532 "/xyz/openbmc_project/object_mapper",
533 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700534 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500535 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700536 "xyz.openbmc_project.Inventory.Decorator.Asset",
537 "xyz.openbmc_project.Inventory.Item.Cpu",
538 "xyz.openbmc_project.Inventory.Item.Dimm",
539 "xyz.openbmc_project.Inventory.Item.System",
540 "xyz.openbmc_project.Common.UUID",
541 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700542}
543
544/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700545 * @brief Retrieves host state properties over dbus
546 *
547 * @param[in] aResp Shared pointer for completing asynchronous calls.
548 *
549 * @return None.
550 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800551inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700552{
553 BMCWEB_LOG_DEBUG << "Get host information.";
554 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800555 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500556 const std::variant<std::string>& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700557 if (ec)
558 {
559 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700560 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700561 return;
562 }
Ed Tanous66173382018-08-15 18:20:59 -0700563
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500564 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700565 BMCWEB_LOG_DEBUG << "Host state: " << *s;
566 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700567 {
Ed Tanous66173382018-08-15 18:20:59 -0700568 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800569 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700570 {
Ed Tanous66173382018-08-15 18:20:59 -0700571 aResp->res.jsonValue["PowerState"] = "On";
572 aResp->res.jsonValue["Status"]["State"] = "Enabled";
573 }
Andrew Geissler83935af2020-02-13 10:24:53 -0600574 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Gunnar Mills8c888602020-05-01 14:25:09 -0500575 "Quiesced")
576 {
577 aResp->res.jsonValue["PowerState"] = "On";
578 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
579 }
580 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Andrew Geissler83935af2020-02-13 10:24:53 -0600581 "DiagnosticMode")
582 {
583 aResp->res.jsonValue["PowerState"] = "On";
584 aResp->res.jsonValue["Status"]["State"] = "InTest";
585 }
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600586 else if (*s == "xyz.openbmc_project.State.Host.HostState."
587 "TransitioningToRunning")
588 {
589 aResp->res.jsonValue["PowerState"] = "PoweringOn";
Noah Brewer15c27bf2021-04-27 15:24:25 -0500590 aResp->res.jsonValue["Status"]["State"] = "Starting";
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600591 }
592 else if (*s == "xyz.openbmc_project.State.Host.HostState."
593 "TransitioningToOff")
594 {
595 aResp->res.jsonValue["PowerState"] = "PoweringOff";
596 aResp->res.jsonValue["Status"]["State"] = "Disabled";
597 }
Ed Tanous66173382018-08-15 18:20:59 -0700598 else
599 {
600 aResp->res.jsonValue["PowerState"] = "Off";
601 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700602 }
603 }
604 },
605 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700606 "org.freedesktop.DBus.Properties", "Get",
607 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700608}
609
610/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500611 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530612 *
613 * @param[in] dbusSource The boot source in DBUS speak.
614 *
615 * @return Returns as a string, the boot source in Redfish terms. If translation
616 * cannot be done, returns an empty string.
617 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000618inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530619{
620 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
621 {
622 return "None";
623 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700624 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530625 {
626 return "Hdd";
627 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700628 if (dbusSource ==
629 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 {
631 return "Cd";
632 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700633 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530634 {
635 return "Pxe";
636 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700637 if (dbusSource ==
638 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700639 {
640 return "Usb";
641 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700642 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530643}
644
645/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300646 * @brief Translates boot type DBUS property value to redfish.
647 *
648 * @param[in] dbusType The boot type in DBUS speak.
649 *
650 * @return Returns as a string, the boot type in Redfish terms. If translation
651 * cannot be done, returns an empty string.
652 */
653inline std::string dbusToRfBootType(const std::string& dbusType)
654{
655 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
656 {
657 return "Legacy";
658 }
659 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
660 {
661 return "UEFI";
662 }
663 return "";
664}
665
666/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500667 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668 *
669 * @param[in] dbusMode The boot mode in DBUS speak.
670 *
671 * @return Returns as a string, the boot mode in Redfish terms. If translation
672 * cannot be done, returns an empty string.
673 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000674inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530675{
676 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
677 {
678 return "None";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "Diags";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685 {
686 return "BiosSetup";
687 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700688 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530689}
690
691/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500692 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530693 *
694 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700695 * @param[out] bootSource The DBus source
696 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530697 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700698 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530699 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800700inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500701 const std::string& rfSource,
702 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530703{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300704 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
705 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700706
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530707 if (rfSource == "None")
708 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700709 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530710 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700711 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530712 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700713 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
714 }
715 else if (rfSource == "Hdd")
716 {
717 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
718 }
719 else if (rfSource == "Diags")
720 {
721 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
722 }
723 else if (rfSource == "Cd")
724 {
725 bootSource =
726 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
727 }
728 else if (rfSource == "BiosSetup")
729 {
730 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700732 else if (rfSource == "Usb")
733 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700734 bootSource =
735 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700736 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530737 else
738 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700739 BMCWEB_LOG_DEBUG << "Invalid property value for "
740 "BootSourceOverrideTarget: "
741 << bootSource;
742 messages::propertyValueNotInList(aResp->res, rfSource,
743 "BootSourceTargetOverride");
744 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530745 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700746 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530747}
Ali Ahmed19817712021-06-29 17:01:52 -0500748
Andrew Geissler978b8802020-11-19 13:36:40 -0600749/**
750 * @brief Retrieves boot progress of the system
751 *
752 * @param[in] aResp Shared pointer for generating response message.
753 *
754 * @return None.
755 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800756inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600757{
758 crow::connections::systemBus->async_method_call(
759 [aResp](const boost::system::error_code ec,
760 const std::variant<std::string>& bootProgress) {
761 if (ec)
762 {
763 // BootProgress is an optional object so just do nothing if
764 // not found
765 return;
766 }
767
768 const std::string* bootProgressStr =
769 std::get_if<std::string>(&bootProgress);
770
771 if (!bootProgressStr)
772 {
773 // Interface implemented but property not found, return error
774 // for that
775 messages::internalError(aResp->res);
776 return;
777 }
778
779 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
780
781 // Now convert the D-Bus BootProgress to the appropriate Redfish
782 // enum
783 std::string rfBpLastState = "None";
784 if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
785 "ProgressStages.Unspecified")
786 {
787 rfBpLastState = "None";
788 }
789 else if (*bootProgressStr ==
790 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
791 "PrimaryProcInit")
792 {
793 rfBpLastState = "PrimaryProcessorInitializationStarted";
794 }
795 else if (*bootProgressStr ==
796 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
797 "BusInit")
798 {
799 rfBpLastState = "BusInitializationStarted";
800 }
801 else if (*bootProgressStr ==
802 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
803 "MemoryInit")
804 {
805 rfBpLastState = "MemoryInitializationStarted";
806 }
807 else if (*bootProgressStr ==
808 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
809 "SecondaryProcInit")
810 {
811 rfBpLastState = "SecondaryProcessorInitializationStarted";
812 }
813 else if (*bootProgressStr ==
814 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
815 "PCIInit")
816 {
817 rfBpLastState = "PCIResourceConfigStarted";
818 }
819 else if (*bootProgressStr ==
820 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
821 "SystemInitComplete")
822 {
823 rfBpLastState = "SystemHardwareInitializationComplete";
824 }
825 else if (*bootProgressStr ==
826 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
827 "OSStart")
828 {
829 rfBpLastState = "OSBootStarted";
830 }
831 else if (*bootProgressStr ==
832 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
833 "OSRunning")
834 {
835 rfBpLastState = "OSRunning";
836 }
837 else
838 {
839 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
840 << *bootProgressStr;
841 // Just return the default
842 }
843
844 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
845 },
846 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
847 "org.freedesktop.DBus.Properties", "Get",
848 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
849}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530850
851/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300852 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300853 *
854 * @param[in] aResp Shared pointer for generating response message.
855 *
856 * @return None.
857 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300858
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300859inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300860{
861 crow::connections::systemBus->async_method_call(
862 [aResp](const boost::system::error_code ec,
863 const std::variant<std::string>& bootType) {
864 if (ec)
865 {
866 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300867 return;
868 }
869
870 const std::string* bootTypeStr =
871 std::get_if<std::string>(&bootType);
872
873 if (!bootTypeStr)
874 {
875 messages::internalError(aResp->res);
876 return;
877 }
878
879 BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
880
881 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode@Redfish."
882 "AllowableValues"] = {"Legacy",
883 "UEFI"};
884
885 auto rfType = dbusToRfBootType(*bootTypeStr);
886 if (rfType.empty())
887 {
888 messages::internalError(aResp->res);
889 return;
890 }
891
892 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300893 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300894 "xyz.openbmc_project.Settings",
895 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300896 "org.freedesktop.DBus.Properties", "Get",
897 "xyz.openbmc_project.Control.Boot.Type", "BootType");
898}
899
900/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300901 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530902 *
903 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530904 *
905 * @return None.
906 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300907
908inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530909{
910 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300911 [aResp](const boost::system::error_code ec,
912 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530913 if (ec)
914 {
915 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
916 messages::internalError(aResp->res);
917 return;
918 }
919
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500920 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530921 std::get_if<std::string>(&bootMode);
922
923 if (!bootModeStr)
924 {
925 messages::internalError(aResp->res);
926 return;
927 }
928
929 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
930
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530931 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
932 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700933 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530934
935 if (*bootModeStr !=
936 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
937 {
938 auto rfMode = dbusToRfBootMode(*bootModeStr);
939 if (!rfMode.empty())
940 {
941 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
942 rfMode;
943 }
944 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530945 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300946 "xyz.openbmc_project.Settings",
947 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530948 "org.freedesktop.DBus.Properties", "Get",
949 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
950}
951
952/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300953 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530954 *
955 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530956 *
957 * @return None.
958 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300959
960inline void
961 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530962{
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530963 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300964 [aResp](const boost::system::error_code ec,
965 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530966 if (ec)
967 {
968 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
969 messages::internalError(aResp->res);
970 return;
971 }
972
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500973 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 std::get_if<std::string>(&bootSource);
975
976 if (!bootSourceStr)
977 {
978 messages::internalError(aResp->res);
979 return;
980 }
981 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
982
983 auto rfSource = dbusToRfBootSource(*bootSourceStr);
984 if (!rfSource.empty())
985 {
986 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
987 rfSource;
988 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300989
990 // Get BootMode as BootSourceOverrideTarget is constructed
991 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300992 getBootOverrideMode(aResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530993 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300994 "xyz.openbmc_project.Settings",
995 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530996 "org.freedesktop.DBus.Properties", "Get",
997 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530998}
999
1000/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001001 * @brief This functions abstracts all the logic behind getting a
1002 * "BootSourceOverrideEnabled" property from an overall boot override enable
1003 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301004 *
1005 * @param[in] aResp Shared pointer for generating response message.
1006 *
1007 * @return None.
1008 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301009
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001010inline void
1011 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1012 const bool bootOverrideEnableSetting)
1013{
1014 if (!bootOverrideEnableSetting)
1015 {
1016 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1017 return;
1018 }
1019
1020 // If boot source override is enabled, we need to check 'one_time'
1021 // property to set a correct value for the "BootSourceOverrideEnabled"
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001023 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001024 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301025 if (ec)
1026 {
1027 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001028 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029 return;
1030 }
1031
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001032 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301033
1034 if (!oneTimePtr)
1035 {
1036 messages::internalError(aResp->res);
1037 return;
1038 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001039
1040 bool oneTimeSetting = *oneTimePtr;
1041
1042 if (oneTimeSetting)
1043 {
1044 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1045 "Once";
1046 }
1047 else
1048 {
1049 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1050 "Continuous";
1051 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301052 },
1053 "xyz.openbmc_project.Settings",
1054 "/xyz/openbmc_project/control/host0/boot/one_time",
1055 "org.freedesktop.DBus.Properties", "Get",
1056 "xyz.openbmc_project.Object.Enable", "Enabled");
1057}
1058
1059/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001060 * @brief Retrieves boot override enable over DBUS
1061 *
1062 * @param[in] aResp Shared pointer for generating response message.
1063 *
1064 * @return None.
1065 */
1066
1067inline void
1068 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1069{
1070 crow::connections::systemBus->async_method_call(
1071 [aResp](const boost::system::error_code ec,
1072 const std::variant<bool>& bootOverrideEnable) {
1073 if (ec)
1074 {
1075 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1076 messages::internalError(aResp->res);
1077 return;
1078 }
1079
1080 const bool* bootOverrideEnablePtr =
1081 std::get_if<bool>(&bootOverrideEnable);
1082
1083 if (!bootOverrideEnablePtr)
1084 {
1085 messages::internalError(aResp->res);
1086 return;
1087 }
1088
1089 processBootOverrideEnable(aResp, *bootOverrideEnablePtr);
1090 },
1091 "xyz.openbmc_project.Settings",
1092 "/xyz/openbmc_project/control/host0/boot",
1093 "org.freedesktop.DBus.Properties", "Get",
1094 "xyz.openbmc_project.Object.Enable", "Enabled");
1095}
1096
1097/**
1098 * @brief Retrieves boot source override properties
1099 *
1100 * @param[in] aResp Shared pointer for generating response message.
1101 *
1102 * @return None.
1103 */
1104inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1105{
1106 BMCWEB_LOG_DEBUG << "Get boot information.";
1107
1108 getBootOverrideSource(aResp);
1109 getBootOverrideType(aResp);
1110 getBootOverrideEnable(aResp);
1111}
1112
1113/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001114 * @brief Retrieves the Last Reset Time
1115 *
1116 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1117 * and power off. Even though this is the "system" Redfish object look at the
1118 * chassis D-Bus interface for the LastStateChangeTime since this has the
1119 * last power operation time.
1120 *
1121 * @param[in] aResp Shared pointer for generating response message.
1122 *
1123 * @return None.
1124 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001125inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001126{
1127 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1128
1129 crow::connections::systemBus->async_method_call(
1130 [aResp](const boost::system::error_code ec,
1131 std::variant<uint64_t>& lastResetTime) {
1132 if (ec)
1133 {
1134 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1135 return;
1136 }
1137
1138 const uint64_t* lastResetTimePtr =
1139 std::get_if<uint64_t>(&lastResetTime);
1140
1141 if (!lastResetTimePtr)
1142 {
1143 messages::internalError(aResp->res);
1144 return;
1145 }
1146 // LastStateChangeTime is epoch time, in milliseconds
1147 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1148 time_t lastResetTimeStamp =
1149 static_cast<time_t>(*lastResetTimePtr / 1000);
1150
1151 // Convert to ISO 8601 standard
1152 aResp->res.jsonValue["LastResetTime"] =
1153 crow::utility::getDateTime(lastResetTimeStamp);
1154 },
1155 "xyz.openbmc_project.State.Chassis",
1156 "/xyz/openbmc_project/state/chassis0",
1157 "org.freedesktop.DBus.Properties", "Get",
1158 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1159}
1160
1161/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001162 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1163 *
1164 * @param[in] aResp Shared pointer for generating response message.
1165 *
1166 * @return None.
1167 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001168inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001169{
1170 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1171
1172 crow::connections::systemBus->async_method_call(
1173 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001174 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001175 if (ec)
1176 {
1177 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1178 return;
1179 }
1180
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001181 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001182 std::get_if<bool>(&autoRebootEnabled);
1183
1184 if (!autoRebootEnabledPtr)
1185 {
1186 messages::internalError(aResp->res);
1187 return;
1188 }
1189
1190 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1191 if (*autoRebootEnabledPtr == true)
1192 {
1193 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1194 "RetryAttempts";
1195 // If AutomaticRetry (AutoReboot) is enabled see how many
1196 // attempts are left
1197 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001198 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001199 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001200 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001201 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001202 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001203 return;
1204 }
1205
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001206 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001207 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1208
1209 if (!autoRebootAttemptsLeftPtr)
1210 {
1211 messages::internalError(aResp->res);
1212 return;
1213 }
1214
1215 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1216 << *autoRebootAttemptsLeftPtr;
1217
1218 aResp->res
1219 .jsonValue["Boot"]
1220 ["RemainingAutomaticRetryAttempts"] =
1221 *autoRebootAttemptsLeftPtr;
1222 },
1223 "xyz.openbmc_project.State.Host",
1224 "/xyz/openbmc_project/state/host0",
1225 "org.freedesktop.DBus.Properties", "Get",
1226 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1227 "AttemptsLeft");
1228 }
1229 else
1230 {
1231 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1232 "Disabled";
1233 }
1234
1235 // Not on D-Bus. Hardcoded here:
1236 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1237 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001238
1239 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1240 // and RetryAttempts. OpenBMC only supports Disabled and
1241 // RetryAttempts.
1242 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1243 "AllowableValues"] = {"Disabled",
1244 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001245 },
1246 "xyz.openbmc_project.Settings",
1247 "/xyz/openbmc_project/control/host0/auto_reboot",
1248 "org.freedesktop.DBus.Properties", "Get",
1249 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1250}
1251
1252/**
George Liuc6a620f2020-04-10 17:18:11 +08001253 * @brief Retrieves power restore policy over DBUS.
1254 *
1255 * @param[in] aResp Shared pointer for generating response message.
1256 *
1257 * @return None.
1258 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001259inline void
1260 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001261{
1262 BMCWEB_LOG_DEBUG << "Get power restore policy";
1263
1264 crow::connections::systemBus->async_method_call(
1265 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001266 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001267 if (ec)
1268 {
1269 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1270 return;
1271 }
1272
1273 const boost::container::flat_map<std::string, std::string>
1274 policyMaps = {
1275 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1276 "AlwaysOn",
1277 "AlwaysOn"},
1278 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1279 "AlwaysOff",
1280 "AlwaysOff"},
1281 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001282 "Restore",
George Liuc6a620f2020-04-10 17:18:11 +08001283 "LastState"}};
1284
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001285 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001286
1287 if (!policyPtr)
1288 {
1289 messages::internalError(aResp->res);
1290 return;
1291 }
1292
1293 auto policyMapsIt = policyMaps.find(*policyPtr);
1294 if (policyMapsIt == policyMaps.end())
1295 {
1296 messages::internalError(aResp->res);
1297 return;
1298 }
1299
1300 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1301 },
1302 "xyz.openbmc_project.Settings",
1303 "/xyz/openbmc_project/control/host0/power_restore_policy",
1304 "org.freedesktop.DBus.Properties", "Get",
1305 "xyz.openbmc_project.Control.Power.RestorePolicy",
1306 "PowerRestorePolicy");
1307}
1308
1309/**
Ali Ahmed19817712021-06-29 17:01:52 -05001310 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1311 * TPM is required for booting the host.
1312 *
1313 * @param[in] aResp Shared pointer for generating response message.
1314 *
1315 * @return None.
1316 */
1317inline void getTrustedModuleRequiredToBoot(
1318 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1319{
1320 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1321
1322 crow::connections::systemBus->async_method_call(
1323 [aResp](
1324 const boost::system::error_code ec,
1325 std::vector<std::pair<
1326 std::string,
1327 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1328 subtree) {
1329 if (ec)
1330 {
1331 BMCWEB_LOG_DEBUG
1332 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1333 // This is an optional D-Bus object so just return if
1334 // error occurs
1335 return;
1336 }
1337 if (subtree.size() == 0)
1338 {
1339 // As noted above, this is an optional interface so just return
1340 // if there is no instance found
1341 return;
1342 }
1343
1344 /* When there is more than one TPMEnable object... */
1345 if (subtree.size() > 1)
1346 {
1347 BMCWEB_LOG_DEBUG
1348 << "DBUS response has more than 1 TPM Enable object:"
1349 << subtree.size();
1350 // Throw an internal Error and return
1351 messages::internalError(aResp->res);
1352 return;
1353 }
1354
1355 // Make sure the Dbus response map has a service and objectPath
1356 // field
1357 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1358 {
1359 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1360 messages::internalError(aResp->res);
1361 return;
1362 }
1363
1364 const std::string& path = subtree[0].first;
1365 const std::string& serv = subtree[0].second.begin()->first;
1366
1367 // Valid TPM Enable object found, now reading the current value
1368 crow::connections::systemBus->async_method_call(
1369 [aResp](const boost::system::error_code ec,
1370 std::variant<bool>& tpmRequired) {
1371 if (ec)
1372 {
1373 BMCWEB_LOG_DEBUG
1374 << "D-BUS response error on TPM.Policy Get" << ec;
1375 messages::internalError(aResp->res);
1376 return;
1377 }
1378
1379 const bool* tpmRequiredVal =
1380 std::get_if<bool>(&tpmRequired);
1381
1382 if (!tpmRequiredVal)
1383 {
1384 messages::internalError(aResp->res);
1385 return;
1386 }
1387
1388 if (*tpmRequiredVal == true)
1389 {
1390 aResp->res
1391 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1392 "Required";
1393 }
1394 else
1395 {
1396 aResp->res
1397 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1398 "Disabled";
1399 }
1400 },
1401 serv, path, "org.freedesktop.DBus.Properties", "Get",
1402 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1403 },
1404 "xyz.openbmc_project.ObjectMapper",
1405 "/xyz/openbmc_project/object_mapper",
1406 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1407 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1408}
1409
1410/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001411 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1412 * TPM is required for booting the host.
1413 *
1414 * @param[in] aResp Shared pointer for generating response message.
1415 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1416 *
1417 * @return None.
1418 */
1419inline void setTrustedModuleRequiredToBoot(
1420 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1421{
1422 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1423
1424 crow::connections::systemBus->async_method_call(
1425 [aResp, tpmRequired](
1426 const boost::system::error_code ec,
1427 std::vector<std::pair<
1428 std::string,
1429 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1430 subtree) {
1431 if (ec)
1432 {
1433 BMCWEB_LOG_DEBUG
1434 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1435 messages::internalError(aResp->res);
1436 return;
1437 }
1438 if (subtree.size() == 0)
1439 {
1440 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1441 "TrustedModuleRequiredToBoot");
1442 return;
1443 }
1444
1445 /* When there is more than one TPMEnable object... */
1446 if (subtree.size() > 1)
1447 {
1448 BMCWEB_LOG_DEBUG
1449 << "DBUS response has more than 1 TPM Enable object:"
1450 << subtree.size();
1451 // Throw an internal Error and return
1452 messages::internalError(aResp->res);
1453 return;
1454 }
1455
1456 // Make sure the Dbus response map has a service and objectPath
1457 // field
1458 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1459 {
1460 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1461 messages::internalError(aResp->res);
1462 return;
1463 }
1464
1465 const std::string& path = subtree[0].first;
1466 const std::string& serv = subtree[0].second.begin()->first;
1467
1468 if (serv.empty())
1469 {
1470 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1471 messages::internalError(aResp->res);
1472 return;
1473 }
1474
1475 // Valid TPM Enable object found, now setting the value
1476 crow::connections::systemBus->async_method_call(
1477 [aResp](const boost::system::error_code ec) {
1478 if (ec)
1479 {
1480 BMCWEB_LOG_DEBUG << "DBUS response error: Set "
1481 "TrustedModuleRequiredToBoot"
1482 << ec;
1483 messages::internalError(aResp->res);
1484 return;
1485 }
1486 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1487 },
1488 serv, path, "org.freedesktop.DBus.Properties", "Set",
1489 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1490 std::variant<bool>(tpmRequired));
1491 },
1492 "xyz.openbmc_project.ObjectMapper",
1493 "/xyz/openbmc_project/object_mapper",
1494 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1495 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1496}
1497
1498/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301499 * @brief Sets boot properties into DBUS object(s).
1500 *
1501 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001502 * @param[in] bootType The boot type to set.
1503 * @return Integer error code.
1504 */
1505inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001506 const std::optional<std::string>& bootType)
1507{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001508 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001509
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001510 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001511 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001512 return;
1513 }
1514
1515 // Source target specified
1516 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1517 // Figure out which DBUS interface and property to use
1518 if (*bootType == "Legacy")
1519 {
1520 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1521 }
1522 else if (*bootType == "UEFI")
1523 {
1524 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1525 }
1526 else
1527 {
1528 BMCWEB_LOG_DEBUG << "Invalid property value for "
1529 "BootSourceOverrideMode: "
1530 << *bootType;
1531 messages::propertyValueNotInList(aResp->res, *bootType,
1532 "BootSourceOverrideMode");
1533 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001534 }
1535
1536 // Act on validated parameters
1537 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1538
1539 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001540 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001541 if (ec)
1542 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001543 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1544 if (ec.value() == boost::asio::error::host_unreachable)
1545 {
1546 messages::resourceNotFound(aResp->res, "Set", "BootType");
1547 return;
1548 }
1549 messages::internalError(aResp->res);
1550 return;
1551 }
1552 BMCWEB_LOG_DEBUG << "Boot type update done.";
1553 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001554 "xyz.openbmc_project.Settings",
1555 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001556 "org.freedesktop.DBus.Properties", "Set",
1557 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1558 std::variant<std::string>(bootTypeStr));
1559}
1560
1561/**
1562 * @brief Sets boot properties into DBUS object(s).
1563 *
1564 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001565 * @param[in] bootType The boot type to set.
1566 * @return Integer error code.
1567 */
1568inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1569 const std::optional<std::string>& bootEnable)
1570{
1571 if (!bootEnable)
1572 {
1573 return;
1574 }
1575 // Source target specified
1576 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1577
1578 bool bootOverrideEnable = false;
1579 bool bootOverridePersistent = false;
1580 // Figure out which DBUS interface and property to use
1581 if (*bootEnable == "Disabled")
1582 {
1583 bootOverrideEnable = false;
1584 }
1585 else if (*bootEnable == "Once")
1586 {
1587 bootOverrideEnable = true;
1588 bootOverridePersistent = false;
1589 }
1590 else if (*bootEnable == "Continuous")
1591 {
1592 bootOverrideEnable = true;
1593 bootOverridePersistent = true;
1594 }
1595 else
1596 {
1597 BMCWEB_LOG_DEBUG << "Invalid property value for "
1598 "BootSourceOverrideEnabled: "
1599 << *bootEnable;
1600 messages::propertyValueNotInList(aResp->res, *bootEnable,
1601 "BootSourceOverrideEnabled");
1602 return;
1603 }
1604
1605 // Act on validated parameters
1606 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1607
1608 crow::connections::systemBus->async_method_call(
1609 [aResp](const boost::system::error_code ec) {
1610 if (ec)
1611 {
1612 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1613 messages::internalError(aResp->res);
1614 return;
1615 }
1616 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1617 },
1618 "xyz.openbmc_project.Settings",
1619 "/xyz/openbmc_project/control/host0/boot",
1620 "org.freedesktop.DBus.Properties", "Set",
1621 "xyz.openbmc_project.Object.Enable", "Enabled",
1622 std::variant<bool>(bootOverrideEnable));
1623
1624 if (!bootOverrideEnable)
1625 {
1626 return;
1627 }
1628
1629 // In case boot override is enabled we need to set correct value for the
1630 // 'one_time' enable DBus interface
1631 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1632 << bootOverridePersistent;
1633
1634 crow::connections::systemBus->async_method_call(
1635 [aResp](const boost::system::error_code ec) {
1636 if (ec)
1637 {
1638 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1639 messages::internalError(aResp->res);
1640 return;
1641 }
1642 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1643 },
1644 "xyz.openbmc_project.Settings",
1645 "/xyz/openbmc_project/control/host0/boot/one_time",
1646 "org.freedesktop.DBus.Properties", "Set",
1647 "xyz.openbmc_project.Object.Enable", "Enabled",
1648 std::variant<bool>(!bootOverridePersistent));
1649}
1650
1651/**
1652 * @brief Sets boot properties into DBUS object(s).
1653 *
1654 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301655 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301656 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001657 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301658 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001659inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001660 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301661{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001662 std::string bootSourceStr;
1663 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001664
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001665 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301666 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001667 return;
1668 }
1669
1670 // Source target specified
1671 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1672 // Figure out which DBUS interface and property to use
1673 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1674 {
1675 BMCWEB_LOG_DEBUG
1676 << "Invalid property value for BootSourceOverrideTarget: "
1677 << *bootSource;
1678 messages::propertyValueNotInList(aResp->res, *bootSource,
1679 "BootSourceTargetOverride");
1680 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001681 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301682
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001683 // Act on validated parameters
1684 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1685 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001686
1687 crow::connections::systemBus->async_method_call(
1688 [aResp](const boost::system::error_code ec) {
1689 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301690 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001691 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1692 messages::internalError(aResp->res);
1693 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301694 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001695 BMCWEB_LOG_DEBUG << "Boot source update done.";
1696 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001697 "xyz.openbmc_project.Settings",
1698 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001699 "org.freedesktop.DBus.Properties", "Set",
1700 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1701 std::variant<std::string>(bootSourceStr));
1702
1703 crow::connections::systemBus->async_method_call(
1704 [aResp](const boost::system::error_code ec) {
1705 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301706 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001707 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1708 messages::internalError(aResp->res);
1709 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301710 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001711 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1712 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001713 "xyz.openbmc_project.Settings",
1714 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001715 "org.freedesktop.DBus.Properties", "Set",
1716 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1717 std::variant<std::string>(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001718}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001719
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001720/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001721 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301722 *
1723 * @param[in] aResp Shared pointer for generating response message.
1724 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001725 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301726 * @param[in] bootEnable The boot override enable from incoming RF request.
1727 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001728 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301729 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001730
1731inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1732 const std::optional<std::string>& bootSource,
1733 const std::optional<std::string>& bootType,
1734 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301735{
1736 BMCWEB_LOG_DEBUG << "Set boot information.";
1737
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001738 setBootModeOrSource(aResp, bootSource);
1739 setBootType(aResp, bootType);
1740 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301741}
1742
George Liuc6a620f2020-04-10 17:18:11 +08001743/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001744 * @brief Sets AssetTag
1745 *
1746 * @param[in] aResp Shared pointer for generating response message.
1747 * @param[in] assetTag "AssetTag" from request.
1748 *
1749 * @return None.
1750 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001751inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001752 const std::string& assetTag)
1753{
1754 crow::connections::systemBus->async_method_call(
1755 [aResp, assetTag](
1756 const boost::system::error_code ec,
1757 const std::vector<std::pair<
1758 std::string,
1759 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1760 subtree) {
1761 if (ec)
1762 {
1763 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1764 messages::internalError(aResp->res);
1765 return;
1766 }
1767 if (subtree.size() == 0)
1768 {
1769 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1770 messages::internalError(aResp->res);
1771 return;
1772 }
1773 // Assume only 1 system D-Bus object
1774 // Throw an error if there is more than 1
1775 if (subtree.size() > 1)
1776 {
1777 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1778 messages::internalError(aResp->res);
1779 return;
1780 }
1781 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1782 {
1783 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1784 messages::internalError(aResp->res);
1785 return;
1786 }
1787
1788 const std::string& path = subtree[0].first;
1789 const std::string& service = subtree[0].second.begin()->first;
1790
1791 if (service.empty())
1792 {
1793 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1794 messages::internalError(aResp->res);
1795 return;
1796 }
1797
1798 crow::connections::systemBus->async_method_call(
1799 [aResp](const boost::system::error_code ec2) {
1800 if (ec2)
1801 {
1802 BMCWEB_LOG_DEBUG
1803 << "D-Bus response error on AssetTag Set " << ec2;
1804 messages::internalError(aResp->res);
1805 return;
1806 }
1807 },
1808 service, path, "org.freedesktop.DBus.Properties", "Set",
1809 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1810 std::variant<std::string>(assetTag));
1811 },
1812 "xyz.openbmc_project.ObjectMapper",
1813 "/xyz/openbmc_project/object_mapper",
1814 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1815 "/xyz/openbmc_project/inventory", int32_t(0),
1816 std::array<const char*, 1>{
1817 "xyz.openbmc_project.Inventory.Item.System"});
1818}
1819
1820/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001821 * @brief Sets automaticRetry (Auto Reboot)
1822 *
1823 * @param[in] aResp Shared pointer for generating response message.
1824 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1825 *
1826 * @return None.
1827 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001828inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001829 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001830{
1831 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1832
1833 // OpenBMC only supports "Disabled" and "RetryAttempts".
1834 bool autoRebootEnabled;
1835
1836 if (automaticRetryConfig == "Disabled")
1837 {
1838 autoRebootEnabled = false;
1839 }
1840 else if (automaticRetryConfig == "RetryAttempts")
1841 {
1842 autoRebootEnabled = true;
1843 }
1844 else
1845 {
1846 BMCWEB_LOG_DEBUG << "Invalid property value for "
1847 "AutomaticRetryConfig: "
1848 << automaticRetryConfig;
1849 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1850 "AutomaticRetryConfig");
1851 return;
1852 }
1853
1854 crow::connections::systemBus->async_method_call(
1855 [aResp](const boost::system::error_code ec) {
1856 if (ec)
1857 {
1858 messages::internalError(aResp->res);
1859 return;
1860 }
1861 },
1862 "xyz.openbmc_project.Settings",
1863 "/xyz/openbmc_project/control/host0/auto_reboot",
1864 "org.freedesktop.DBus.Properties", "Set",
1865 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1866 std::variant<bool>(autoRebootEnabled));
1867}
1868
1869/**
George Liuc6a620f2020-04-10 17:18:11 +08001870 * @brief Sets power restore policy properties.
1871 *
1872 * @param[in] aResp Shared pointer for generating response message.
1873 * @param[in] policy power restore policy properties from request.
1874 *
1875 * @return None.
1876 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001877inline void
1878 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1879 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001880{
1881 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1882
1883 const boost::container::flat_map<std::string, std::string> policyMaps = {
1884 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1885 "AlwaysOn"},
1886 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1887 "AlwaysOff"},
1888 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001889 "Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001890
1891 std::string powerRestorPolicy;
1892
Gunnar Mills4e69c902021-01-05 19:50:11 -06001893 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001894 if (policyMapsIt == policyMaps.end())
1895 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001896 messages::propertyValueNotInList(aResp->res, policy,
1897 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001898 return;
1899 }
1900
1901 powerRestorPolicy = policyMapsIt->second;
1902
1903 crow::connections::systemBus->async_method_call(
1904 [aResp](const boost::system::error_code ec) {
1905 if (ec)
1906 {
1907 messages::internalError(aResp->res);
1908 return;
1909 }
1910 },
1911 "xyz.openbmc_project.Settings",
1912 "/xyz/openbmc_project/control/host0/power_restore_policy",
1913 "org.freedesktop.DBus.Properties", "Set",
1914 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1915 std::variant<std::string>(powerRestorPolicy));
1916}
1917
AppaRao Pulia6349912019-10-18 17:16:08 +05301918#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1919/**
1920 * @brief Retrieves provisioning status
1921 *
1922 * @param[in] aResp Shared pointer for completing asynchronous calls.
1923 *
1924 * @return None.
1925 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001926inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301927{
1928 BMCWEB_LOG_DEBUG << "Get OEM information.";
1929 crow::connections::systemBus->async_method_call(
1930 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001931 const std::vector<std::pair<std::string, VariantType>>&
1932 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301933 nlohmann::json& oemPFR =
1934 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001935 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1936 "#OemComputerSystem.OpenBmc";
1937 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1938
AppaRao Pulia6349912019-10-18 17:16:08 +05301939 if (ec)
1940 {
1941 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301942 // not an error, don't have to have the interface
1943 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301944 return;
1945 }
1946
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001947 const bool* provState = nullptr;
1948 const bool* lockState = nullptr;
1949 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301950 propertiesList)
1951 {
1952 if (property.first == "UfmProvisioned")
1953 {
1954 provState = std::get_if<bool>(&property.second);
1955 }
1956 else if (property.first == "UfmLocked")
1957 {
1958 lockState = std::get_if<bool>(&property.second);
1959 }
1960 }
1961
1962 if ((provState == nullptr) || (lockState == nullptr))
1963 {
1964 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1965 messages::internalError(aResp->res);
1966 return;
1967 }
1968
AppaRao Pulia6349912019-10-18 17:16:08 +05301969 if (*provState == true)
1970 {
1971 if (*lockState == true)
1972 {
1973 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1974 }
1975 else
1976 {
1977 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1978 }
1979 }
1980 else
1981 {
1982 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1983 }
1984 },
1985 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1986 "org.freedesktop.DBus.Properties", "GetAll",
1987 "xyz.openbmc_project.PFR.Attributes");
1988}
1989#endif
1990
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301991/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001992 * @brief Translate the PowerMode to a response message.
1993 *
1994 * @param[in] aResp Shared pointer for generating response message.
1995 * @param[in] modeValue PowerMode value to be translated
1996 *
1997 * @return None.
1998 */
1999inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2000 const std::string& modeValue)
2001{
2002 std::string modeString;
2003
2004 if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2005 "PowerMode.Static")
2006 {
2007 aResp->res.jsonValue["PowerMode"] = "Static";
2008 }
2009 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2010 "PowerMode.MaximumPerformance")
2011 {
2012 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2013 }
2014 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2015 "PowerMode.PowerSaving")
2016 {
2017 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2018 }
2019 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2020 "PowerMode.OEM")
2021 {
2022 aResp->res.jsonValue["PowerMode"] = "OEM";
2023 }
2024 else
2025 {
2026 // Any other values would be invalid
2027 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2028 messages::internalError(aResp->res);
2029 }
2030}
2031
2032/**
2033 * @brief Retrieves system power mode
2034 *
2035 * @param[in] aResp Shared pointer for generating response message.
2036 *
2037 * @return None.
2038 */
2039inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2040{
2041 BMCWEB_LOG_DEBUG << "Get power mode.";
2042
2043 // Get Power Mode object path:
2044 crow::connections::systemBus->async_method_call(
2045 [aResp](
2046 const boost::system::error_code ec,
2047 const std::vector<std::pair<
2048 std::string,
2049 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2050 subtree) {
2051 if (ec)
2052 {
2053 BMCWEB_LOG_DEBUG
2054 << "DBUS response error on Power.Mode GetSubTree " << ec;
2055 // This is an optional D-Bus object so just return if
2056 // error occurs
2057 return;
2058 }
2059 if (subtree.empty())
2060 {
2061 // As noted above, this is an optional interface so just return
2062 // if there is no instance found
2063 return;
2064 }
2065 if (subtree.size() > 1)
2066 {
2067 // More then one PowerMode object is not supported and is an
2068 // error
2069 BMCWEB_LOG_DEBUG
2070 << "Found more than 1 system D-Bus Power.Mode objects: "
2071 << subtree.size();
2072 messages::internalError(aResp->res);
2073 return;
2074 }
2075 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2076 {
2077 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2078 messages::internalError(aResp->res);
2079 return;
2080 }
2081 const std::string& path = subtree[0].first;
2082 const std::string& service = subtree[0].second.begin()->first;
2083 if (service.empty())
2084 {
2085 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2086 messages::internalError(aResp->res);
2087 return;
2088 }
2089 // Valid Power Mode object found, now read the current value
2090 crow::connections::systemBus->async_method_call(
2091 [aResp](const boost::system::error_code ec,
2092 const std::variant<std::string>& pmode) {
2093 if (ec)
2094 {
2095 BMCWEB_LOG_DEBUG
2096 << "DBUS response error on PowerMode Get: " << ec;
2097 messages::internalError(aResp->res);
2098 return;
2099 }
2100
2101 const std::string* s = std::get_if<std::string>(&pmode);
2102 if (s == nullptr)
2103 {
2104 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2105 messages::internalError(aResp->res);
2106 return;
2107 }
2108
2109 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2110 {"Static", "MaximumPerformance", "PowerSaving"};
2111
2112 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2113 translatePowerMode(aResp, *s);
2114 },
2115 service, path, "org.freedesktop.DBus.Properties", "Get",
2116 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2117 },
2118 "xyz.openbmc_project.ObjectMapper",
2119 "/xyz/openbmc_project/object_mapper",
2120 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2121 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2122}
2123
2124/**
2125 * @brief Validate the specified mode is valid and return the PowerMode
2126 * name associated with that string
2127 *
2128 * @param[in] aResp Shared pointer for generating response message.
2129 * @param[in] modeString String representing the desired PowerMode
2130 *
2131 * @return PowerMode value or empty string if mode is not valid
2132 */
2133inline std::string
2134 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2135 const std::string& modeString)
2136{
2137 std::string mode;
2138
2139 if (modeString == "Static")
2140 {
2141 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2142 }
2143 else if (modeString == "MaximumPerformance")
2144 {
2145 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
2146 "MaximumPerformance";
2147 }
2148 else if (modeString == "PowerSaving")
2149 {
2150 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2151 }
2152 else
2153 {
2154 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2155 }
2156 return mode;
2157}
2158
2159/**
2160 * @brief Sets system power mode.
2161 *
2162 * @param[in] aResp Shared pointer for generating response message.
2163 * @param[in] pmode System power mode from request.
2164 *
2165 * @return None.
2166 */
2167inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2168 const std::string& pmode)
2169{
2170 BMCWEB_LOG_DEBUG << "Set power mode.";
2171
2172 std::string powerMode = validatePowerMode(aResp, pmode);
2173 if (powerMode.empty())
2174 {
2175 return;
2176 }
2177
2178 // Get Power Mode object path:
2179 crow::connections::systemBus->async_method_call(
2180 [aResp, powerMode](
2181 const boost::system::error_code ec,
2182 const std::vector<std::pair<
2183 std::string,
2184 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2185 subtree) {
2186 if (ec)
2187 {
2188 BMCWEB_LOG_DEBUG
2189 << "DBUS response error on Power.Mode GetSubTree " << ec;
2190 // This is an optional D-Bus object, but user attempted to patch
2191 messages::internalError(aResp->res);
2192 return;
2193 }
2194 if (subtree.empty())
2195 {
2196 // This is an optional D-Bus object, but user attempted to patch
2197 messages::resourceNotFound(aResp->res, "ComputerSystem",
2198 "PowerMode");
2199 return;
2200 }
2201 if (subtree.size() > 1)
2202 {
2203 // More then one PowerMode object is not supported and is an
2204 // error
2205 BMCWEB_LOG_DEBUG
2206 << "Found more than 1 system D-Bus Power.Mode objects: "
2207 << subtree.size();
2208 messages::internalError(aResp->res);
2209 return;
2210 }
2211 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2212 {
2213 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2214 messages::internalError(aResp->res);
2215 return;
2216 }
2217 const std::string& path = subtree[0].first;
2218 const std::string& service = subtree[0].second.begin()->first;
2219 if (service.empty())
2220 {
2221 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2222 messages::internalError(aResp->res);
2223 return;
2224 }
2225
2226 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2227 << path;
2228
2229 // Set the Power Mode property
2230 crow::connections::systemBus->async_method_call(
2231 [aResp](const boost::system::error_code ec) {
2232 if (ec)
2233 {
2234 messages::internalError(aResp->res);
2235 return;
2236 }
2237 },
2238 service, path, "org.freedesktop.DBus.Properties", "Set",
2239 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2240 std::variant<std::string>(powerMode));
2241 },
2242 "xyz.openbmc_project.ObjectMapper",
2243 "/xyz/openbmc_project/object_mapper",
2244 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2245 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2246}
2247
2248/**
Yong Li51709ff2019-09-30 14:13:04 +08002249 * @brief Translates watchdog timeout action DBUS property value to redfish.
2250 *
2251 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2252 *
2253 * @return Returns as a string, the timeout action in Redfish terms. If
2254 * translation cannot be done, returns an empty string.
2255 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002256inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002257{
2258 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2259 {
2260 return "None";
2261 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002262 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002263 {
2264 return "ResetSystem";
2265 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002266 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002267 {
2268 return "PowerDown";
2269 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002270 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002271 {
2272 return "PowerCycle";
2273 }
2274
2275 return "";
2276}
2277
2278/**
Yong Lic45f0082019-10-10 14:19:01 +08002279 *@brief Translates timeout action from Redfish to DBUS property value.
2280 *
2281 *@param[in] rfAction The timeout action in Redfish.
2282 *
2283 *@return Returns as a string, the time_out action as expected by DBUS.
2284 *If translation cannot be done, returns an empty string.
2285 */
2286
Ed Tanous23a21a12020-07-25 04:45:05 +00002287inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002288{
2289 if (rfAction == "None")
2290 {
2291 return "xyz.openbmc_project.State.Watchdog.Action.None";
2292 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002293 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002294 {
2295 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2296 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002297 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002298 {
2299 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2300 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002301 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002302 {
2303 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2304 }
2305
2306 return "";
2307}
2308
2309/**
Yong Li51709ff2019-09-30 14:13:04 +08002310 * @brief Retrieves host watchdog timer properties over DBUS
2311 *
2312 * @param[in] aResp Shared pointer for completing asynchronous calls.
2313 *
2314 * @return None.
2315 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002316inline void
2317 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002318{
2319 BMCWEB_LOG_DEBUG << "Get host watchodg";
2320 crow::connections::systemBus->async_method_call(
2321 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002322 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002323 if (ec)
2324 {
2325 // watchdog service is stopped
2326 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2327 return;
2328 }
2329
2330 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2331
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002332 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002333 aResp->res.jsonValue["HostWatchdogTimer"];
2334
2335 // watchdog service is running/enabled
2336 hostWatchdogTimer["Status"]["State"] = "Enabled";
2337
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002338 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002339 {
2340 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2341 if (property.first == "Enabled")
2342 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002343 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002344
2345 if (!state)
2346 {
2347 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002348 return;
Yong Li51709ff2019-09-30 14:13:04 +08002349 }
2350
2351 hostWatchdogTimer["FunctionEnabled"] = *state;
2352 }
2353 else if (property.first == "ExpireAction")
2354 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002355 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002356 std::get_if<std::string>(&property.second);
2357 if (!s)
2358 {
2359 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002360 return;
Yong Li51709ff2019-09-30 14:13:04 +08002361 }
2362
2363 std::string action = dbusToRfWatchdogAction(*s);
2364 if (action.empty())
2365 {
2366 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002367 return;
Yong Li51709ff2019-09-30 14:13:04 +08002368 }
2369 hostWatchdogTimer["TimeoutAction"] = action;
2370 }
2371 }
2372 },
2373 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2374 "org.freedesktop.DBus.Properties", "GetAll",
2375 "xyz.openbmc_project.State.Watchdog");
2376}
2377
2378/**
Yong Lic45f0082019-10-10 14:19:01 +08002379 * @brief Sets Host WatchDog Timer properties.
2380 *
2381 * @param[in] aResp Shared pointer for generating response message.
2382 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2383 * RF request.
2384 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2385 *
2386 * @return None.
2387 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002388inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002389 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002390 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002391{
2392 BMCWEB_LOG_DEBUG << "Set host watchdog";
2393
2394 if (wdtTimeOutAction)
2395 {
2396 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2397 // check if TimeOut Action is Valid
2398 if (wdtTimeOutActStr.empty())
2399 {
2400 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2401 << *wdtTimeOutAction;
2402 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2403 "TimeoutAction");
2404 return;
2405 }
2406
2407 crow::connections::systemBus->async_method_call(
2408 [aResp](const boost::system::error_code ec) {
2409 if (ec)
2410 {
2411 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2412 messages::internalError(aResp->res);
2413 return;
2414 }
2415 },
2416 "xyz.openbmc_project.Watchdog",
2417 "/xyz/openbmc_project/watchdog/host0",
2418 "org.freedesktop.DBus.Properties", "Set",
2419 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2420 std::variant<std::string>(wdtTimeOutActStr));
2421 }
2422
2423 if (wdtEnable)
2424 {
2425 crow::connections::systemBus->async_method_call(
2426 [aResp](const boost::system::error_code ec) {
2427 if (ec)
2428 {
2429 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2430 messages::internalError(aResp->res);
2431 return;
2432 }
2433 },
2434 "xyz.openbmc_project.Watchdog",
2435 "/xyz/openbmc_project/watchdog/host0",
2436 "org.freedesktop.DBus.Properties", "Set",
2437 "xyz.openbmc_project.State.Watchdog", "Enabled",
2438 std::variant<bool>(*wdtEnable));
2439 }
2440}
2441
2442/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002443 * SystemsCollection derived class for delivering ComputerSystems Collection
2444 * Schema
2445 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002446inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002447{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002448 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002449 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002450 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002451 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002452 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2453 asyncResp->res.jsonValue["@odata.type"] =
2454 "#ComputerSystemCollection.ComputerSystemCollection";
2455 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2456 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002457
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002458 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002459 [asyncResp](const boost::system::error_code ec,
2460 const std::variant<std::string>& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002461 nlohmann::json& ifaceArray =
2462 asyncResp->res.jsonValue["Members"];
2463 ifaceArray = nlohmann::json::array();
2464 auto& count =
2465 asyncResp->res.jsonValue["Members@odata.count"];
2466 ifaceArray.push_back(
2467 {{"@odata.id", "/redfish/v1/Systems/system"}});
2468 count = ifaceArray.size();
2469 if (!ec)
2470 {
2471 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2472 ifaceArray.push_back(
2473 {{"@odata.id",
2474 "/redfish/v1/Systems/hypervisor"}});
2475 count = ifaceArray.size();
2476 }
2477 },
2478 "xyz.openbmc_project.Settings",
2479 "/xyz/openbmc_project/network/hypervisor",
2480 "org.freedesktop.DBus.Properties", "Get",
2481 "xyz.openbmc_project.Network.SystemConfiguration",
2482 "HostName");
2483 });
2484}
Sunitha Harish462023a2020-02-19 08:34:59 -06002485
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002486/**
2487 * Function transceives data with dbus directly.
2488 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002489inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002490{
2491 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2492 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2493 constexpr char const* interfaceName =
2494 "xyz.openbmc_project.Control.Host.NMI";
2495 constexpr char const* method = "NMI";
2496
2497 crow::connections::systemBus->async_method_call(
2498 [asyncResp](const boost::system::error_code ec) {
2499 if (ec)
2500 {
2501 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2502 messages::internalError(asyncResp->res);
2503 return;
2504 }
2505 messages::success(asyncResp->res);
2506 },
2507 serviceName, objectPath, interfaceName, method);
2508}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002509
2510/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002511 * SystemActionsReset class supports handle POST method for Reset action.
2512 * The class retrieves and sends data directly to D-Bus.
2513 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002514inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002515{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002516 /**
2517 * Function handles POST method request.
2518 * Analyzes POST body message before sends Reset request data to D-Bus.
2519 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002520 BMCWEB_ROUTE(app,
2521 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002522 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002523 .methods(
2524 boost::beast::http::verb::
2525 post)([](const crow::Request& req,
2526 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2527 std::string resetType;
2528 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2529 resetType))
2530 {
2531 return;
2532 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002533
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002534 // Get the command and host vs. chassis
2535 std::string command;
2536 bool hostCommand;
2537 if ((resetType == "On") || (resetType == "ForceOn"))
2538 {
2539 command = "xyz.openbmc_project.State.Host.Transition.On";
2540 hostCommand = true;
2541 }
2542 else if (resetType == "ForceOff")
2543 {
2544 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2545 hostCommand = false;
2546 }
2547 else if (resetType == "ForceRestart")
2548 {
2549 command =
2550 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2551 hostCommand = true;
2552 }
2553 else if (resetType == "GracefulShutdown")
2554 {
2555 command = "xyz.openbmc_project.State.Host.Transition.Off";
2556 hostCommand = true;
2557 }
2558 else if (resetType == "GracefulRestart")
2559 {
2560 command = "xyz.openbmc_project.State.Host.Transition."
2561 "GracefulWarmReboot";
2562 hostCommand = true;
2563 }
2564 else if (resetType == "PowerCycle")
2565 {
2566 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2567 hostCommand = true;
2568 }
2569 else if (resetType == "Nmi")
2570 {
2571 doNMI(asyncResp);
2572 return;
2573 }
2574 else
2575 {
2576 messages::actionParameterUnknown(asyncResp->res, "Reset",
2577 resetType);
2578 return;
2579 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002580
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002581 if (hostCommand)
2582 {
2583 crow::connections::systemBus->async_method_call(
2584 [asyncResp, resetType](const boost::system::error_code ec) {
2585 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002586 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002587 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2588 if (ec.value() ==
2589 boost::asio::error::invalid_argument)
2590 {
2591 messages::actionParameterNotSupported(
2592 asyncResp->res, resetType, "Reset");
2593 }
2594 else
2595 {
2596 messages::internalError(asyncResp->res);
2597 }
2598 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002599 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002600 messages::success(asyncResp->res);
2601 },
2602 "xyz.openbmc_project.State.Host",
2603 "/xyz/openbmc_project/state/host0",
2604 "org.freedesktop.DBus.Properties", "Set",
2605 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2606 std::variant<std::string>{command});
2607 }
2608 else
2609 {
2610 crow::connections::systemBus->async_method_call(
2611 [asyncResp, resetType](const boost::system::error_code ec) {
2612 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002613 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002614 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2615 if (ec.value() ==
2616 boost::asio::error::invalid_argument)
2617 {
2618 messages::actionParameterNotSupported(
2619 asyncResp->res, resetType, "Reset");
2620 }
2621 else
2622 {
2623 messages::internalError(asyncResp->res);
2624 }
2625 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002626 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002627 messages::success(asyncResp->res);
2628 },
2629 "xyz.openbmc_project.State.Chassis",
2630 "/xyz/openbmc_project/state/chassis0",
2631 "org.freedesktop.DBus.Properties", "Set",
2632 "xyz.openbmc_project.State.Chassis",
2633 "RequestedPowerTransition",
2634 std::variant<std::string>{command});
2635 }
2636 });
2637}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002638
2639/**
Ed Tanous66173382018-08-15 18:20:59 -07002640 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002641 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002642inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002643{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002644
Ed Tanous1abe55e2018-09-05 08:30:59 -07002645 /**
2646 * Functions triggers appropriate requests on DBus
2647 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002648 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002649 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002650 .methods(
2651 boost::beast::http::verb::
2652 get)([](const crow::Request&,
2653 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2654 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain3a2d04242021-05-28 16:57:10 -05002655 "#ComputerSystem.v1_15_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002656 asyncResp->res.jsonValue["Name"] = "system";
2657 asyncResp->res.jsonValue["Id"] = "system";
2658 asyncResp->res.jsonValue["SystemType"] = "Physical";
2659 asyncResp->res.jsonValue["Description"] = "Computer System";
2660 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2661 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2662 "Disabled";
2663 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2664 uint64_t(0);
2665 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2666 "Disabled";
2667 asyncResp->res.jsonValue["@odata.id"] =
2668 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002669
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002670 asyncResp->res.jsonValue["Processors"] = {
2671 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2672 asyncResp->res.jsonValue["Memory"] = {
2673 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2674 asyncResp->res.jsonValue["Storage"] = {
2675 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002676
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002677 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2678 {"target",
2679 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2680 {"@Redfish.ActionInfo",
2681 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002682
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002683 asyncResp->res.jsonValue["LogServices"] = {
2684 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002685
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002686 asyncResp->res.jsonValue["Bios"] = {
2687 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002688
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002689 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2690 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002691
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002692 asyncResp->res.jsonValue["Status"] = {
2693 {"Health", "OK"},
2694 {"State", "Enabled"},
2695 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002696
2697 // Fill in SerialConsole info
2698 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2699 15;
2700 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2701 {"ServiceEnabled", true},
2702 };
2703 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2704 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2705 {"ServiceEnabled", true},
2706 {"Port", 2200},
2707 // https://github.com/openbmc/docs/blob/master/console.md
2708 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2709 };
2710
2711#ifdef BMCWEB_ENABLE_KVM
2712 // Fill in GraphicalConsole info
2713 asyncResp->res.jsonValue["GraphicalConsole"] = {
2714 {"ServiceEnabled", true},
2715 {"MaxConcurrentSessions", 4},
2716 {"ConnectTypesSupported", {"KVMIP"}},
2717 };
2718#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002719 constexpr const std::array<const char*, 4> inventoryForSystems = {
2720 "xyz.openbmc_project.Inventory.Item.Dimm",
2721 "xyz.openbmc_project.Inventory.Item.Cpu",
2722 "xyz.openbmc_project.Inventory.Item.Drive",
2723 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002724
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002725 auto health = std::make_shared<HealthPopulate>(asyncResp);
2726 crow::connections::systemBus->async_method_call(
2727 [health](const boost::system::error_code ec,
2728 std::vector<std::string>& resp) {
2729 if (ec)
2730 {
2731 // no inventory
2732 return;
2733 }
2734
2735 health->inventory = std::move(resp);
2736 },
2737 "xyz.openbmc_project.ObjectMapper",
2738 "/xyz/openbmc_project/object_mapper",
2739 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2740 int32_t(0), inventoryForSystems);
2741
2742 health->populate();
2743
2744 getMainChassisId(
2745 asyncResp, [](const std::string& chassisId,
2746 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2747 aRsp->res.jsonValue["Links"]["Chassis"] = {
2748 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2749 });
2750
2751 getLocationIndicatorActive(asyncResp);
2752 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2753 getIndicatorLedState(asyncResp);
2754 getComputerSystem(asyncResp, health);
2755 getHostState(asyncResp);
2756 getBootProperties(asyncResp);
2757 getBootProgress(asyncResp);
2758 getPCIeDeviceList(asyncResp, "PCIeDevices");
2759 getHostWatchdogTimer(asyncResp);
2760 getPowerRestorePolicy(asyncResp);
2761 getAutomaticRetry(asyncResp);
2762 getLastResetTime(asyncResp);
2763#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2764 getProvisioningStatus(asyncResp);
2765#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002766 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002767 getPowerMode(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002768 });
2769 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002770 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002771 .methods(boost::beast::http::verb::patch)(
2772 [](const crow::Request& req,
2773 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2774 std::optional<bool> locationIndicatorActive;
2775 std::optional<std::string> indicatorLed;
2776 std::optional<nlohmann::json> bootProps;
2777 std::optional<nlohmann::json> wdtTimerProps;
2778 std::optional<std::string> assetTag;
2779 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002780 std::optional<std::string> powerMode;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05002781 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002782 if (!json_util::readJson(
2783 req, asyncResp->res, "IndicatorLED", indicatorLed,
2784 "LocationIndicatorActive", locationIndicatorActive,
2785 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2786 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Ali Ahmed1c05dae2021-06-29 17:49:22 -05002787 assetTag, "PowerMode", powerMode,
2788 "TrustedModuleRequiredToBoot",
2789 trustedModuleRequiredToBoot))
James Feistb49ac872019-05-21 15:12:01 -07002790 {
James Feistb49ac872019-05-21 15:12:01 -07002791 return;
2792 }
2793
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002794 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07002795
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002796 if (assetTag)
2797 {
2798 setAssetTag(asyncResp, *assetTag);
2799 }
James Feistb49ac872019-05-21 15:12:01 -07002800
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002801 if (wdtTimerProps)
2802 {
2803 std::optional<bool> wdtEnable;
2804 std::optional<std::string> wdtTimeOutAction;
2805
2806 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
2807 "FunctionEnabled", wdtEnable,
2808 "TimeoutAction", wdtTimeOutAction))
2809 {
2810 return;
2811 }
2812 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
2813 }
2814
2815 if (bootProps)
2816 {
2817 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002818 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 std::optional<std::string> bootEnable;
2820 std::optional<std::string> automaticRetryConfig;
2821
2822 if (!json_util::readJson(
2823 *bootProps, asyncResp->res,
2824 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002825 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002826 "BootSourceOverrideEnabled", bootEnable,
2827 "AutomaticRetryConfig", automaticRetryConfig))
2828 {
2829 return;
2830 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03002831
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002832 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002833 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03002834 setBootProperties(asyncResp, bootSource, bootType,
2835 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002836 }
2837 if (automaticRetryConfig)
2838 {
2839 setAutomaticRetry(asyncResp, *automaticRetryConfig);
2840 }
2841 }
2842
2843 if (locationIndicatorActive)
2844 {
2845 setLocationIndicatorActive(asyncResp,
2846 *locationIndicatorActive);
2847 }
2848
2849 // TODO (Gunnar): Remove IndicatorLED after enough time has
2850 // passed
2851 if (indicatorLed)
2852 {
2853 setIndicatorLedState(asyncResp, *indicatorLed);
2854 asyncResp->res.addHeader(
2855 boost::beast::http::field::warning,
2856 "299 - \"IndicatorLED is deprecated. Use "
2857 "LocationIndicatorActive instead.\"");
2858 }
2859
2860 if (powerRestorePolicy)
2861 {
2862 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
2863 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002864
2865 if (powerMode)
2866 {
2867 setPowerMode(asyncResp, *powerMode);
2868 }
Ali Ahmed1c05dae2021-06-29 17:49:22 -05002869
2870 if (trustedModuleRequiredToBoot)
2871 {
2872 setTrustedModuleRequiredToBoot(
2873 asyncResp, *trustedModuleRequiredToBoot);
2874 }
zhanghch058d1b46d2021-04-01 11:18:24 +08002875 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002876}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302877
2878/**
2879 * SystemResetActionInfo derived class for delivering Computer Systems
2880 * ResetType AllowableValues using ResetInfo schema.
2881 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302883{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302884
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302885 /**
2886 * Functions triggers appropriate requests on DBus
2887 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002888 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07002889 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002890 .methods(boost::beast::http::verb::get)(
2891 [](const crow::Request&,
2892 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2893 asyncResp->res.jsonValue = {
2894 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
2895 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
2896 {"Name", "Reset Action Info"},
2897 {"Id", "ResetActionInfo"},
2898 {"Parameters",
2899 {{{"Name", "ResetType"},
2900 {"Required", true},
2901 {"DataType", "String"},
2902 {"AllowableValues",
2903 {"On", "ForceOff", "ForceOn", "ForceRestart",
2904 "GracefulRestart", "GracefulShutdown", "PowerCycle",
2905 "Nmi"}}}}}};
2906 });
2907}
Ed Tanous1abe55e2018-09-05 08:30:59 -07002908} // namespace redfish