blob: 5ad065b3518a77188e4ab7d09dcf3de4d0a1e1eb [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
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500329 if (properties.size() > 0)
330 {
Zhikui Ren9cf21522020-09-10 11:13:14 -0700331 const uint64_t* processorId = nullptr;
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700332 const std::string* procFamily = nullptr;
333 nlohmann::json& procSummary =
334 aResp->res.jsonValue["ProcessorSumm"
335 "ary"];
336 nlohmann::json& procCount =
337 procSummary["Count"];
338
339 auto procCountPtr = procCount.get_ptr<
340 nlohmann::json::
341 number_integer_t*>();
342 if (procCountPtr == nullptr)
343 {
344 messages::internalError(aResp->res);
345 return;
346 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500347 for (const auto& property : properties)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500348 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700349
Zhikui Ren9cf21522020-09-10 11:13:14 -0700350 if (property.first == "Id")
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700351 {
352 processorId =
Zhikui Ren9cf21522020-09-10 11:13:14 -0700353 std::get_if<uint64_t>(
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700354 &property.second);
355 if (nullptr != procFamily)
Ed Tanous3174e4d2020-10-07 11:41:22 -0700356 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700357 break;
Ed Tanous3174e4d2020-10-07 11:41:22 -0700358 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700359 continue;
360 }
361
Zhikui Ren9cf21522020-09-10 11:13:14 -0700362 if (property.first == "Family")
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500363 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700364 procFamily =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500365 std::get_if<std::string>(
366 &property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700367 if (nullptr != processorId)
Ed Tanous3174e4d2020-10-07 11:41:22 -0700368 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700369 break;
Ed Tanous3174e4d2020-10-07 11:41:22 -0700370 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700371 continue;
372 }
373 }
James Feistb4b95952019-12-05 15:01:55 -0800374
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700375 if (procFamily != nullptr &&
376 processorId != nullptr)
377 {
378 if (procCountPtr != nullptr &&
379 *processorId != 0)
380 {
381 *procCountPtr += 1;
382 procSummary["Status"]["State"] =
383 "Enabled";
384
385 procSummary["Model"] =
386 *procFamily;
Ed Tanous6c34de42018-08-29 13:37:36 -0700387 }
388 }
Ed Tanous029573d2019-02-01 10:57:49 -0800389 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500390 else
391 {
392 auto getCpuPresenceState =
393 [aResp](
394 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000395 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500396 const std::variant<bool>&
397 cpuPresenceCheck) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000398 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500399 {
400 BMCWEB_LOG_ERROR
401 << "DBUS response "
402 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000403 << ec3;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500404 return;
405 }
406 modifyCpuPresenceState(
407 aResp, cpuPresenceCheck);
408 };
409
410 auto getCpuFunctionalState =
411 [aResp](
412 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000413 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500414 const std::variant<bool>&
415 cpuFunctionalCheck) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000416 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500417 {
418 BMCWEB_LOG_ERROR
419 << "DBUS response "
420 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000421 << ec3;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500422 return;
423 }
424 modifyCpuFunctionalState(
425 aResp, cpuFunctionalCheck);
426 };
427 // Get the Presence of CPU
428 crow::connections::systemBus
429 ->async_method_call(
430 std::move(getCpuPresenceState),
431 service, path,
432 "org.freedesktop.DBus."
433 "Properties",
434 "Get",
435 "xyz.openbmc_project.Inventory."
436 "Item",
437 "Present");
438
439 // Get the Functional State
440 crow::connections::systemBus
441 ->async_method_call(
442 std::move(
443 getCpuFunctionalState),
444 service, path,
445 "org.freedesktop.DBus."
446 "Properties",
447 "Get",
448 "xyz.openbmc_project.State."
449 "Decorator."
450 "OperationalStatus",
451 "Functional");
452
453 // Get the MODEL from
454 // xyz.openbmc_project.Inventory.Decorator.Asset
455 // support it later as Model is Empty
456 // currently.
457 }
Ed Tanous029573d2019-02-01 10:57:49 -0800458 },
459 connection.first, path,
460 "org.freedesktop.DBus.Properties", "GetAll",
461 "xyz.openbmc_project.Inventory.Item.Cpu");
James Feist5bc2dc82019-10-22 14:33:16 -0700462
463 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800464 }
465 else if (interfaceName ==
466 "xyz.openbmc_project.Common.UUID")
467 {
468 BMCWEB_LOG_DEBUG
469 << "Found UUID, now get its properties.";
470 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500471 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000472 const boost::system::error_code ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500473 const std::vector<
474 std::pair<std::string, VariantType>>&
475 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000476 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800477 {
478 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000479 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800480 messages::internalError(aResp->res);
481 return;
482 }
483 BMCWEB_LOG_DEBUG << "Got "
484 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500485 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800486 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500487 VariantType>&
488 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800489 {
Ed Tanous029573d2019-02-01 10:57:49 -0800490 if (property.first == "UUID")
491 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500492 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500493 std::get_if<std::string>(
494 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700495
Ed Tanous029573d2019-02-01 10:57:49 -0800496 if (value != nullptr)
497 {
498 std::string valueStr = *value;
499 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700500 {
Ed Tanous029573d2019-02-01 10:57:49 -0800501 valueStr.insert(8, 1, '-');
502 valueStr.insert(13, 1, '-');
503 valueStr.insert(18, 1, '-');
504 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700505 }
Ed Tanous029573d2019-02-01 10:57:49 -0800506 BMCWEB_LOG_DEBUG << "UUID = "
507 << valueStr;
508 aResp->res.jsonValue["UUID"] =
509 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700510 }
511 }
Ed Tanous029573d2019-02-01 10:57:49 -0800512 }
513 },
514 connection.first, path,
515 "org.freedesktop.DBus.Properties", "GetAll",
516 "xyz.openbmc_project.Common.UUID");
517 }
518 else if (interfaceName ==
519 "xyz.openbmc_project.Inventory.Item.System")
520 {
521 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500522 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000523 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500524 const std::vector<
525 std::pair<std::string, VariantType>>&
526 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000527 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800528 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700529 // doesn't have to include this
530 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800531 return;
532 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500533 BMCWEB_LOG_DEBUG
534 << "Got " << propertiesList.size()
535 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800536 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500537 VariantType>&
538 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800539 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500540 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600541 property.first;
542 if ((propertyName == "PartNumber") ||
543 (propertyName == "SerialNumber") ||
544 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500545 (propertyName == "Model") ||
546 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800547 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500548 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600549 std::get_if<std::string>(
550 &property.second);
551 if (value != nullptr)
552 {
553 aResp->res
554 .jsonValue[propertyName] =
555 *value;
556 }
Ed Tanous029573d2019-02-01 10:57:49 -0800557 }
558 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500559
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600560 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500561 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600562 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500563 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800564 },
565 connection.first, path,
566 "org.freedesktop.DBus.Properties", "GetAll",
567 "xyz.openbmc_project.Inventory.Decorator."
568 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700569
570 crow::connections::systemBus->async_method_call(
571 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000572 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500573 const std::variant<std::string>& property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000574 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700575 {
576 // doesn't have to include this
577 // interface
578 return;
579 }
580
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500581 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700582 std::get_if<std::string>(&property);
583 if (value != nullptr)
584 {
585 aResp->res.jsonValue["AssetTag"] =
586 *value;
587 }
588 },
589 connection.first, path,
590 "org.freedesktop.DBus.Properties", "Get",
591 "xyz.openbmc_project.Inventory.Decorator."
592 "AssetTag",
593 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700594 }
595 }
596 }
597 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700598 },
599 "xyz.openbmc_project.ObjectMapper",
600 "/xyz/openbmc_project/object_mapper",
601 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700602 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500603 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700604 "xyz.openbmc_project.Inventory.Decorator.Asset",
605 "xyz.openbmc_project.Inventory.Item.Cpu",
606 "xyz.openbmc_project.Inventory.Item.Dimm",
607 "xyz.openbmc_project.Inventory.Item.System",
608 "xyz.openbmc_project.Common.UUID",
609 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700610}
611
612/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700613 * @brief Retrieves host state properties over dbus
614 *
615 * @param[in] aResp Shared pointer for completing asynchronous calls.
616 *
617 * @return None.
618 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800619inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700620{
621 BMCWEB_LOG_DEBUG << "Get host information.";
622 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800623 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500624 const std::variant<std::string>& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700625 if (ec)
626 {
627 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700628 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700629 return;
630 }
Ed Tanous66173382018-08-15 18:20:59 -0700631
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500632 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700633 BMCWEB_LOG_DEBUG << "Host state: " << *s;
634 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700635 {
Ed Tanous66173382018-08-15 18:20:59 -0700636 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800637 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700638 {
Ed Tanous66173382018-08-15 18:20:59 -0700639 aResp->res.jsonValue["PowerState"] = "On";
640 aResp->res.jsonValue["Status"]["State"] = "Enabled";
641 }
Andrew Geissler83935af2020-02-13 10:24:53 -0600642 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Gunnar Mills8c888602020-05-01 14:25:09 -0500643 "Quiesced")
644 {
645 aResp->res.jsonValue["PowerState"] = "On";
646 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
647 }
648 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Andrew Geissler83935af2020-02-13 10:24:53 -0600649 "DiagnosticMode")
650 {
651 aResp->res.jsonValue["PowerState"] = "On";
652 aResp->res.jsonValue["Status"]["State"] = "InTest";
653 }
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600654 else if (*s == "xyz.openbmc_project.State.Host.HostState."
655 "TransitioningToRunning")
656 {
657 aResp->res.jsonValue["PowerState"] = "PoweringOn";
Noah Brewer15c27bf2021-04-27 15:24:25 -0500658 aResp->res.jsonValue["Status"]["State"] = "Starting";
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600659 }
660 else if (*s == "xyz.openbmc_project.State.Host.HostState."
661 "TransitioningToOff")
662 {
663 aResp->res.jsonValue["PowerState"] = "PoweringOff";
664 aResp->res.jsonValue["Status"]["State"] = "Disabled";
665 }
Ed Tanous66173382018-08-15 18:20:59 -0700666 else
667 {
668 aResp->res.jsonValue["PowerState"] = "Off";
669 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700670 }
671 }
672 },
673 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700674 "org.freedesktop.DBus.Properties", "Get",
675 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700676}
677
678/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500679 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530680 *
681 * @param[in] dbusSource The boot source in DBUS speak.
682 *
683 * @return Returns as a string, the boot source in Redfish terms. If translation
684 * cannot be done, returns an empty string.
685 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000686inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530687{
688 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
689 {
690 return "None";
691 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700692 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530693 {
694 return "Hdd";
695 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700696 if (dbusSource ==
697 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530698 {
699 return "Cd";
700 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700701 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530702 {
703 return "Pxe";
704 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700705 if (dbusSource ==
706 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700707 {
708 return "Usb";
709 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700710 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530711}
712
713/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300714 * @brief Translates boot type DBUS property value to redfish.
715 *
716 * @param[in] dbusType The boot type in DBUS speak.
717 *
718 * @return Returns as a string, the boot type in Redfish terms. If translation
719 * cannot be done, returns an empty string.
720 */
721inline std::string dbusToRfBootType(const std::string& dbusType)
722{
723 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
724 {
725 return "Legacy";
726 }
727 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
728 {
729 return "UEFI";
730 }
731 return "";
732}
733
734/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500735 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530736 *
737 * @param[in] dbusMode The boot mode in DBUS speak.
738 *
739 * @return Returns as a string, the boot mode in Redfish terms. If translation
740 * cannot be done, returns an empty string.
741 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000742inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530743{
744 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
745 {
746 return "None";
747 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700748 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530749 {
750 return "Diags";
751 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700752 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530753 {
754 return "BiosSetup";
755 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700756 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530757}
758
759/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500760 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530761 *
762 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700763 * @param[out] bootSource The DBus source
764 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530765 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530767 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800768inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500769 const std::string& rfSource,
770 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530771{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700772 // The caller has initialized the bootSource and bootMode to:
773 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
774 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
775 // Only modify the bootSource/bootMode variable needed to achieve the
776 // desired boot action.
777
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 if (rfSource == "None")
779 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700782 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530783 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700784 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
785 }
786 else if (rfSource == "Hdd")
787 {
788 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
789 }
790 else if (rfSource == "Diags")
791 {
792 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
793 }
794 else if (rfSource == "Cd")
795 {
796 bootSource =
797 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
798 }
799 else if (rfSource == "BiosSetup")
800 {
801 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530802 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700803 else if (rfSource == "Usb")
804 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700805 bootSource =
806 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700807 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530808 else
809 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700810 BMCWEB_LOG_DEBUG << "Invalid property value for "
811 "BootSourceOverrideTarget: "
812 << bootSource;
813 messages::propertyValueNotInList(aResp->res, rfSource,
814 "BootSourceTargetOverride");
815 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530816 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700817 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818}
Ali Ahmed19817712021-06-29 17:01:52 -0500819
Andrew Geissler978b8802020-11-19 13:36:40 -0600820/**
821 * @brief Retrieves boot progress of the system
822 *
823 * @param[in] aResp Shared pointer for generating response message.
824 *
825 * @return None.
826 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800827inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600828{
829 crow::connections::systemBus->async_method_call(
830 [aResp](const boost::system::error_code ec,
831 const std::variant<std::string>& bootProgress) {
832 if (ec)
833 {
834 // BootProgress is an optional object so just do nothing if
835 // not found
836 return;
837 }
838
839 const std::string* bootProgressStr =
840 std::get_if<std::string>(&bootProgress);
841
842 if (!bootProgressStr)
843 {
844 // Interface implemented but property not found, return error
845 // for that
846 messages::internalError(aResp->res);
847 return;
848 }
849
850 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
851
852 // Now convert the D-Bus BootProgress to the appropriate Redfish
853 // enum
854 std::string rfBpLastState = "None";
855 if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
856 "ProgressStages.Unspecified")
857 {
858 rfBpLastState = "None";
859 }
860 else if (*bootProgressStr ==
861 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
862 "PrimaryProcInit")
863 {
864 rfBpLastState = "PrimaryProcessorInitializationStarted";
865 }
866 else if (*bootProgressStr ==
867 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
868 "BusInit")
869 {
870 rfBpLastState = "BusInitializationStarted";
871 }
872 else if (*bootProgressStr ==
873 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
874 "MemoryInit")
875 {
876 rfBpLastState = "MemoryInitializationStarted";
877 }
878 else if (*bootProgressStr ==
879 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
880 "SecondaryProcInit")
881 {
882 rfBpLastState = "SecondaryProcessorInitializationStarted";
883 }
884 else if (*bootProgressStr ==
885 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
886 "PCIInit")
887 {
888 rfBpLastState = "PCIResourceConfigStarted";
889 }
890 else if (*bootProgressStr ==
891 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
892 "SystemInitComplete")
893 {
894 rfBpLastState = "SystemHardwareInitializationComplete";
895 }
896 else if (*bootProgressStr ==
897 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
898 "OSStart")
899 {
900 rfBpLastState = "OSBootStarted";
901 }
902 else if (*bootProgressStr ==
903 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
904 "OSRunning")
905 {
906 rfBpLastState = "OSRunning";
907 }
908 else
909 {
910 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
911 << *bootProgressStr;
912 // Just return the default
913 }
914
915 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
916 },
917 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
918 "org.freedesktop.DBus.Properties", "Get",
919 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
920}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530921
922/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923 * @brief Checks if the current boot override state can be considered as
924 * Disabled
925 *
926 * @param[in] aResp Shared pointer for generating response message.
927 *
928 * @return None.
929 */
930inline void
931 checkIfOverrideIsDisabled(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
932{
933 // If the BootSourceOverrideTarget is still "None" at the end,
934 // reset the BootSourceOverrideEnabled to indicate that
935 // overrides are disabled
936 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] == "None")
937 {
938 // If the BootSourceOverrideMode is supported we should
939 // check if it is still "UEFI" too
940 if (aResp->res.jsonValue["Boot"].contains("BootSourceOverrideMode"))
941 {
942 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] !=
943 "UEFI")
944 {
945 return;
946 }
947 }
948 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
949 }
950}
951
952/**
953 * @brief Retrieves boot type over DBUS and fills out the response
954 *
955 * @param[in] aResp Shared pointer for generating response message.
956 * @param[in] bootDbusObj The dbus object to query for boot properties.
957 *
958 * @return None.
959 */
960inline void getBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
961 const std::string& bootDbusObj)
962{
963 crow::connections::systemBus->async_method_call(
964 [aResp](const boost::system::error_code ec,
965 const std::variant<std::string>& bootType) {
966 if (ec)
967 {
968 // not an error, don't have to have the interface
969
970 // Support Disabled override state in a way:
971 // "BootSourceOverrideEnabled=Disabled" =
972 // "BootSourceOverrideMode=UEFI" +
973 // "BootSourceOverrideTarget=None"
974 checkIfOverrideIsDisabled(aResp);
975 return;
976 }
977
978 const std::string* bootTypeStr =
979 std::get_if<std::string>(&bootType);
980
981 if (!bootTypeStr)
982 {
983 messages::internalError(aResp->res);
984 return;
985 }
986
987 BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
988
989 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode@Redfish."
990 "AllowableValues"] = {"Legacy",
991 "UEFI"};
992
993 auto rfType = dbusToRfBootType(*bootTypeStr);
994 if (rfType.empty())
995 {
996 messages::internalError(aResp->res);
997 return;
998 }
999
1000 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
1001
1002 // Support Disabled override state in a way:
1003 // "BootSourceOverrideEnabled=Disabled" =
1004 // "BootSourceOverrideMode=UEFI" + "BootSourceOverrideTarget=None"
1005 checkIfOverrideIsDisabled(aResp);
1006 },
1007 "xyz.openbmc_project.Settings", bootDbusObj,
1008 "org.freedesktop.DBus.Properties", "Get",
1009 "xyz.openbmc_project.Control.Boot.Type", "BootType");
1010}
1011
1012/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301013 * @brief Retrieves boot mode over DBUS and fills out the response
1014 *
1015 * @param[in] aResp Shared pointer for generating response message.
1016 * @param[in] bootDbusObj The dbus object to query for boot properties.
1017 *
1018 * @return None.
1019 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001020inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -07001021 const std::string& bootDbusObj)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022{
1023 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001024 [aResp, bootDbusObj](const boost::system::error_code ec,
1025 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026 if (ec)
1027 {
1028 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1029 messages::internalError(aResp->res);
1030 return;
1031 }
1032
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001033 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034 std::get_if<std::string>(&bootMode);
1035
1036 if (!bootModeStr)
1037 {
1038 messages::internalError(aResp->res);
1039 return;
1040 }
1041
1042 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
1043
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
1045 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001046 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301047
1048 if (*bootModeStr !=
1049 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1050 {
1051 auto rfMode = dbusToRfBootMode(*bootModeStr);
1052 if (!rfMode.empty())
1053 {
1054 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1055 rfMode;
1056 }
1057 }
1058
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001059 // Get BootType inside this async call as we need all of the
1060 // BootSource/BootMode/BootType to support
1061 // "BootSourceOverrideEnabled"="Disabled" state.
1062 getBootType(aResp, bootDbusObj);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301063 },
1064 "xyz.openbmc_project.Settings", bootDbusObj,
1065 "org.freedesktop.DBus.Properties", "Get",
1066 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
1067}
1068
1069/**
1070 * @brief Retrieves boot source over DBUS
1071 *
1072 * @param[in] aResp Shared pointer for generating response message.
1073 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
1074 *
1075 * @return None.
1076 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001077inline void getBootSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001078 bool oneTimeEnabled)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301079{
1080 std::string bootDbusObj =
1081 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
1082 : "/xyz/openbmc_project/control/host0/boot";
1083
1084 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
1085 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1086 (oneTimeEnabled) ? "Once" : "Continuous";
1087
1088 crow::connections::systemBus->async_method_call(
1089 [aResp, bootDbusObj](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001090 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301091 if (ec)
1092 {
1093 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1094 messages::internalError(aResp->res);
1095 return;
1096 }
1097
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001098 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301099 std::get_if<std::string>(&bootSource);
1100
1101 if (!bootSourceStr)
1102 {
1103 messages::internalError(aResp->res);
1104 return;
1105 }
1106 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1107
1108 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1109 if (!rfSource.empty())
1110 {
1111 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1112 rfSource;
1113 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001114
1115 // Get BootMode as BootSourceOverrideTarget is constructed
1116 // from both BootSource and BootMode
1117 getBootMode(aResp, bootDbusObj);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301118 },
1119 "xyz.openbmc_project.Settings", bootDbusObj,
1120 "org.freedesktop.DBus.Properties", "Get",
1121 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301122}
1123
1124/**
1125 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1126 * get boot source and boot mode.
1127 *
1128 * @param[in] aResp Shared pointer for generating response message.
1129 *
1130 * @return None.
1131 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001132inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301133{
1134 BMCWEB_LOG_DEBUG << "Get boot information.";
1135
1136 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001137 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001138 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301139 if (ec)
1140 {
1141 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -07001142 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301143 return;
1144 }
1145
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001146 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301147
1148 if (!oneTimePtr)
1149 {
1150 messages::internalError(aResp->res);
1151 return;
1152 }
1153 getBootSource(aResp, *oneTimePtr);
1154 },
1155 "xyz.openbmc_project.Settings",
1156 "/xyz/openbmc_project/control/host0/boot/one_time",
1157 "org.freedesktop.DBus.Properties", "Get",
1158 "xyz.openbmc_project.Object.Enable", "Enabled");
1159}
1160
1161/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001162 * @brief Retrieves the Last Reset Time
1163 *
1164 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1165 * and power off. Even though this is the "system" Redfish object look at the
1166 * chassis D-Bus interface for the LastStateChangeTime since this has the
1167 * last power operation time.
1168 *
1169 * @param[in] aResp Shared pointer for generating response message.
1170 *
1171 * @return None.
1172 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001173inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001174{
1175 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1176
1177 crow::connections::systemBus->async_method_call(
1178 [aResp](const boost::system::error_code ec,
1179 std::variant<uint64_t>& lastResetTime) {
1180 if (ec)
1181 {
1182 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1183 return;
1184 }
1185
1186 const uint64_t* lastResetTimePtr =
1187 std::get_if<uint64_t>(&lastResetTime);
1188
1189 if (!lastResetTimePtr)
1190 {
1191 messages::internalError(aResp->res);
1192 return;
1193 }
1194 // LastStateChangeTime is epoch time, in milliseconds
1195 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1196 time_t lastResetTimeStamp =
1197 static_cast<time_t>(*lastResetTimePtr / 1000);
1198
1199 // Convert to ISO 8601 standard
1200 aResp->res.jsonValue["LastResetTime"] =
1201 crow::utility::getDateTime(lastResetTimeStamp);
1202 },
1203 "xyz.openbmc_project.State.Chassis",
1204 "/xyz/openbmc_project/state/chassis0",
1205 "org.freedesktop.DBus.Properties", "Get",
1206 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1207}
1208
1209/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001210 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1211 *
1212 * @param[in] aResp Shared pointer for generating response message.
1213 *
1214 * @return None.
1215 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001216inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001217{
1218 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1219
1220 crow::connections::systemBus->async_method_call(
1221 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001222 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001223 if (ec)
1224 {
1225 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1226 return;
1227 }
1228
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001229 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001230 std::get_if<bool>(&autoRebootEnabled);
1231
1232 if (!autoRebootEnabledPtr)
1233 {
1234 messages::internalError(aResp->res);
1235 return;
1236 }
1237
1238 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1239 if (*autoRebootEnabledPtr == true)
1240 {
1241 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1242 "RetryAttempts";
1243 // If AutomaticRetry (AutoReboot) is enabled see how many
1244 // attempts are left
1245 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001246 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001247 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001248 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001249 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001250 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001251 return;
1252 }
1253
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001254 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001255 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1256
1257 if (!autoRebootAttemptsLeftPtr)
1258 {
1259 messages::internalError(aResp->res);
1260 return;
1261 }
1262
1263 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1264 << *autoRebootAttemptsLeftPtr;
1265
1266 aResp->res
1267 .jsonValue["Boot"]
1268 ["RemainingAutomaticRetryAttempts"] =
1269 *autoRebootAttemptsLeftPtr;
1270 },
1271 "xyz.openbmc_project.State.Host",
1272 "/xyz/openbmc_project/state/host0",
1273 "org.freedesktop.DBus.Properties", "Get",
1274 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1275 "AttemptsLeft");
1276 }
1277 else
1278 {
1279 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1280 "Disabled";
1281 }
1282
1283 // Not on D-Bus. Hardcoded here:
1284 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1285 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001286
1287 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1288 // and RetryAttempts. OpenBMC only supports Disabled and
1289 // RetryAttempts.
1290 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1291 "AllowableValues"] = {"Disabled",
1292 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001293 },
1294 "xyz.openbmc_project.Settings",
1295 "/xyz/openbmc_project/control/host0/auto_reboot",
1296 "org.freedesktop.DBus.Properties", "Get",
1297 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1298}
1299
1300/**
George Liuc6a620f2020-04-10 17:18:11 +08001301 * @brief Retrieves power restore policy over DBUS.
1302 *
1303 * @param[in] aResp Shared pointer for generating response message.
1304 *
1305 * @return None.
1306 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001307inline void
1308 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001309{
1310 BMCWEB_LOG_DEBUG << "Get power restore policy";
1311
1312 crow::connections::systemBus->async_method_call(
1313 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001314 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001315 if (ec)
1316 {
1317 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1318 return;
1319 }
1320
1321 const boost::container::flat_map<std::string, std::string>
1322 policyMaps = {
1323 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1324 "AlwaysOn",
1325 "AlwaysOn"},
1326 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1327 "AlwaysOff",
1328 "AlwaysOff"},
1329 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001330 "Restore",
George Liuc6a620f2020-04-10 17:18:11 +08001331 "LastState"}};
1332
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001333 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001334
1335 if (!policyPtr)
1336 {
1337 messages::internalError(aResp->res);
1338 return;
1339 }
1340
1341 auto policyMapsIt = policyMaps.find(*policyPtr);
1342 if (policyMapsIt == policyMaps.end())
1343 {
1344 messages::internalError(aResp->res);
1345 return;
1346 }
1347
1348 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1349 },
1350 "xyz.openbmc_project.Settings",
1351 "/xyz/openbmc_project/control/host0/power_restore_policy",
1352 "org.freedesktop.DBus.Properties", "Get",
1353 "xyz.openbmc_project.Control.Power.RestorePolicy",
1354 "PowerRestorePolicy");
1355}
1356
1357/**
Ali Ahmed19817712021-06-29 17:01:52 -05001358 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1359 * TPM is required for booting the host.
1360 *
1361 * @param[in] aResp Shared pointer for generating response message.
1362 *
1363 * @return None.
1364 */
1365inline void getTrustedModuleRequiredToBoot(
1366 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1367{
1368 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1369
1370 crow::connections::systemBus->async_method_call(
1371 [aResp](
1372 const boost::system::error_code ec,
1373 std::vector<std::pair<
1374 std::string,
1375 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1376 subtree) {
1377 if (ec)
1378 {
1379 BMCWEB_LOG_DEBUG
1380 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1381 // This is an optional D-Bus object so just return if
1382 // error occurs
1383 return;
1384 }
1385 if (subtree.size() == 0)
1386 {
1387 // As noted above, this is an optional interface so just return
1388 // if there is no instance found
1389 return;
1390 }
1391
1392 /* When there is more than one TPMEnable object... */
1393 if (subtree.size() > 1)
1394 {
1395 BMCWEB_LOG_DEBUG
1396 << "DBUS response has more than 1 TPM Enable object:"
1397 << subtree.size();
1398 // Throw an internal Error and return
1399 messages::internalError(aResp->res);
1400 return;
1401 }
1402
1403 // Make sure the Dbus response map has a service and objectPath
1404 // field
1405 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1406 {
1407 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1408 messages::internalError(aResp->res);
1409 return;
1410 }
1411
1412 const std::string& path = subtree[0].first;
1413 const std::string& serv = subtree[0].second.begin()->first;
1414
1415 // Valid TPM Enable object found, now reading the current value
1416 crow::connections::systemBus->async_method_call(
1417 [aResp](const boost::system::error_code ec,
1418 std::variant<bool>& tpmRequired) {
1419 if (ec)
1420 {
1421 BMCWEB_LOG_DEBUG
1422 << "D-BUS response error on TPM.Policy Get" << ec;
1423 messages::internalError(aResp->res);
1424 return;
1425 }
1426
1427 const bool* tpmRequiredVal =
1428 std::get_if<bool>(&tpmRequired);
1429
1430 if (!tpmRequiredVal)
1431 {
1432 messages::internalError(aResp->res);
1433 return;
1434 }
1435
1436 if (*tpmRequiredVal == true)
1437 {
1438 aResp->res
1439 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1440 "Required";
1441 }
1442 else
1443 {
1444 aResp->res
1445 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1446 "Disabled";
1447 }
1448 },
1449 serv, path, "org.freedesktop.DBus.Properties", "Get",
1450 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1451 },
1452 "xyz.openbmc_project.ObjectMapper",
1453 "/xyz/openbmc_project/object_mapper",
1454 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1455 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1456}
1457
1458/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301459 * @brief Sets boot properties into DBUS object(s).
1460 *
1461 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001462 * @param[in] overrideEnabled The source override "enable".
1463 * @param[in] bootObj Path to the DBUS object.
1464 * @param[in] bootType The boot type to set.
1465 * @return Integer error code.
1466 */
1467inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1468 const bool overrideEnabled, const std::string& bootObj,
1469 const std::optional<std::string>& bootType)
1470{
1471 std::string bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1472
1473 if (bootType && overrideEnabled)
1474 {
1475 // Source target specified
1476 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1477 // Figure out which DBUS interface and property to use
1478 if (*bootType == "Legacy")
1479 {
1480 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1481 }
1482 else if (*bootType == "UEFI")
1483 {
1484 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1485 }
1486 else
1487 {
1488 BMCWEB_LOG_DEBUG << "Invalid property value for "
1489 "BootSourceOverrideMode: "
1490 << *bootType;
1491 messages::propertyValueNotInList(aResp->res, *bootType,
1492 "BootSourceOverrideMode");
1493 return;
1494 }
1495 }
1496
1497 // Act on validated parameters
1498 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1499
1500 crow::connections::systemBus->async_method_call(
1501 [aResp, bootType](const boost::system::error_code ec) {
1502 if (ec)
1503 {
1504 if (!bootType)
1505 {
1506 // If bootType wasn't explicitly present in the incoming
1507 // message don't output error. The error could come from a
1508 // fact that the BootType interface may be not present in
1509 // the settings object. It could happen because this
1510 // interface is not relevant for some Host architectures
1511 // (for example POWER).
1512 return;
1513 }
1514
1515 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1516 if (ec.value() == boost::asio::error::host_unreachable)
1517 {
1518 messages::resourceNotFound(aResp->res, "Set", "BootType");
1519 return;
1520 }
1521 messages::internalError(aResp->res);
1522 return;
1523 }
1524 BMCWEB_LOG_DEBUG << "Boot type update done.";
1525 },
1526 "xyz.openbmc_project.Settings", bootObj,
1527 "org.freedesktop.DBus.Properties", "Set",
1528 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1529 std::variant<std::string>(bootTypeStr));
1530}
1531
1532/**
1533 * @brief Sets boot properties into DBUS object(s).
1534 *
1535 * @param[in] aResp Shared pointer for generating response message.
1536 * @param[in] overrideEnabled The source override "enable".
1537 * @param[in] bootObj Path to the DBUS object.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301538 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301539 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001540 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301541 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001542inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1543 const bool overrideEnabled,
1544 const std::string& bootObj,
1545 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301546{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001547 std::string bootSourceStr =
1548 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1549 std::string bootModeStr =
1550 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001551
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001552 if (bootSource && overrideEnabled)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301553 {
1554 // Source target specified
1555 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1556 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001557 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1558 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301559 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001560 BMCWEB_LOG_DEBUG
1561 << "Invalid property value for BootSourceOverrideTarget: "
1562 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301563 messages::propertyValueNotInList(aResp->res, *bootSource,
1564 "BootSourceTargetOverride");
1565 return;
1566 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001567 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301568
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001569 // Act on validated parameters
1570 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1571 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001572
1573 crow::connections::systemBus->async_method_call(
1574 [aResp](const boost::system::error_code ec) {
1575 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301576 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001577 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1578 messages::internalError(aResp->res);
1579 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301580 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001581 BMCWEB_LOG_DEBUG << "Boot source update done.";
1582 },
1583 "xyz.openbmc_project.Settings", bootObj,
1584 "org.freedesktop.DBus.Properties", "Set",
1585 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1586 std::variant<std::string>(bootSourceStr));
1587
1588 crow::connections::systemBus->async_method_call(
1589 [aResp](const boost::system::error_code ec) {
1590 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301591 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001592 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1593 messages::internalError(aResp->res);
1594 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301595 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001596 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1597 },
1598 "xyz.openbmc_project.Settings", bootObj,
1599 "org.freedesktop.DBus.Properties", "Set",
1600 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1601 std::variant<std::string>(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001602}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001603
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001604/**
1605 * @brief Sets "One time" enabled setting into DBUS object
1606 *
1607 * @param[in] aResp Shared pointer for generating response message.
1608 * @param[in] oneTime Enable property for one-time object
1609 *
1610 * @return Integer error code.
1611 */
1612inline void setOneTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1613 bool oneTime)
1614{
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301615 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001616 [aResp{aResp}](const boost::system::error_code ec) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301617 if (ec)
1618 {
1619 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1620 messages::internalError(aResp->res);
1621 return;
1622 }
1623 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1624 },
1625 "xyz.openbmc_project.Settings",
1626 "/xyz/openbmc_project/control/host0/boot/one_time",
1627 "org.freedesktop.DBus.Properties", "Set",
1628 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001629 std::variant<bool>(oneTime));
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301630}
1631
1632/**
1633 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1634 * set boot source/boot mode properties.
1635 *
1636 * @param[in] aResp Shared pointer for generating response message.
1637 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001638 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301639 * @param[in] bootEnable The boot override enable from incoming RF request.
1640 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001641 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301642 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001643inline void
1644 setBootSourceProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1645 std::optional<std::string> bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001646 std::optional<std::string> bootType,
zhanghch058d1b46d2021-04-01 11:18:24 +08001647 std::optional<std::string> bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301648{
1649 BMCWEB_LOG_DEBUG << "Set boot information.";
1650
1651 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001652 [aResp, bootSource{std::move(bootSource)},
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001653 bootType{std::move(bootType)},
Patrick Williams19bd78d2020-05-13 17:38:24 -05001654 bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001655 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301656 if (ec)
1657 {
1658 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1659 messages::internalError(aResp->res);
1660 return;
1661 }
1662
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001663 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301664
1665 if (!oneTimePtr)
1666 {
1667 messages::internalError(aResp->res);
1668 return;
1669 }
1670
1671 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1672
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001673 bool oneTimeSetting = *oneTimePtr;
1674 bool overrideEnabled = true;
1675
1676 // Validate incoming parameters
1677 if (bootEnable)
1678 {
1679 if (*bootEnable == "Once")
1680 {
1681 oneTimeSetting = true;
1682 }
1683 else if (*bootEnable == "Continuous")
1684 {
1685 oneTimeSetting = false;
1686 }
1687 else if (*bootEnable == "Disabled")
1688 {
1689 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
1690 oneTimeSetting = false;
1691 overrideEnabled = false;
1692 }
1693 else
1694 {
1695 BMCWEB_LOG_DEBUG << "Unsupported value for "
1696 "BootSourceOverrideEnabled: "
1697 << *bootEnable;
1698 messages::propertyValueNotInList(
1699 aResp->res, *bootEnable, "BootSourceOverrideEnabled");
1700 return;
1701 }
1702 }
1703
1704 std::string bootObj = "/xyz/openbmc_project/control/host0/boot";
1705 if (oneTimeSetting)
1706 {
1707 bootObj += "/one_time";
1708 }
1709
1710 setBootModeOrSource(aResp, overrideEnabled, bootObj, bootSource);
1711 setBootType(aResp, overrideEnabled, bootObj, bootType);
1712 setOneTime(aResp, oneTimeSetting);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301713 },
1714 "xyz.openbmc_project.Settings",
1715 "/xyz/openbmc_project/control/host0/boot/one_time",
1716 "org.freedesktop.DBus.Properties", "Get",
1717 "xyz.openbmc_project.Object.Enable", "Enabled");
1718}
1719
George Liuc6a620f2020-04-10 17:18:11 +08001720/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001721 * @brief Sets AssetTag
1722 *
1723 * @param[in] aResp Shared pointer for generating response message.
1724 * @param[in] assetTag "AssetTag" from request.
1725 *
1726 * @return None.
1727 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001728inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001729 const std::string& assetTag)
1730{
1731 crow::connections::systemBus->async_method_call(
1732 [aResp, assetTag](
1733 const boost::system::error_code ec,
1734 const std::vector<std::pair<
1735 std::string,
1736 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1737 subtree) {
1738 if (ec)
1739 {
1740 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1741 messages::internalError(aResp->res);
1742 return;
1743 }
1744 if (subtree.size() == 0)
1745 {
1746 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1747 messages::internalError(aResp->res);
1748 return;
1749 }
1750 // Assume only 1 system D-Bus object
1751 // Throw an error if there is more than 1
1752 if (subtree.size() > 1)
1753 {
1754 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1755 messages::internalError(aResp->res);
1756 return;
1757 }
1758 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1759 {
1760 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1761 messages::internalError(aResp->res);
1762 return;
1763 }
1764
1765 const std::string& path = subtree[0].first;
1766 const std::string& service = subtree[0].second.begin()->first;
1767
1768 if (service.empty())
1769 {
1770 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1771 messages::internalError(aResp->res);
1772 return;
1773 }
1774
1775 crow::connections::systemBus->async_method_call(
1776 [aResp](const boost::system::error_code ec2) {
1777 if (ec2)
1778 {
1779 BMCWEB_LOG_DEBUG
1780 << "D-Bus response error on AssetTag Set " << ec2;
1781 messages::internalError(aResp->res);
1782 return;
1783 }
1784 },
1785 service, path, "org.freedesktop.DBus.Properties", "Set",
1786 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1787 std::variant<std::string>(assetTag));
1788 },
1789 "xyz.openbmc_project.ObjectMapper",
1790 "/xyz/openbmc_project/object_mapper",
1791 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1792 "/xyz/openbmc_project/inventory", int32_t(0),
1793 std::array<const char*, 1>{
1794 "xyz.openbmc_project.Inventory.Item.System"});
1795}
1796
1797/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001798 * @brief Sets automaticRetry (Auto Reboot)
1799 *
1800 * @param[in] aResp Shared pointer for generating response message.
1801 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1802 *
1803 * @return None.
1804 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001805inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001806 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001807{
1808 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1809
1810 // OpenBMC only supports "Disabled" and "RetryAttempts".
1811 bool autoRebootEnabled;
1812
1813 if (automaticRetryConfig == "Disabled")
1814 {
1815 autoRebootEnabled = false;
1816 }
1817 else if (automaticRetryConfig == "RetryAttempts")
1818 {
1819 autoRebootEnabled = true;
1820 }
1821 else
1822 {
1823 BMCWEB_LOG_DEBUG << "Invalid property value for "
1824 "AutomaticRetryConfig: "
1825 << automaticRetryConfig;
1826 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1827 "AutomaticRetryConfig");
1828 return;
1829 }
1830
1831 crow::connections::systemBus->async_method_call(
1832 [aResp](const boost::system::error_code ec) {
1833 if (ec)
1834 {
1835 messages::internalError(aResp->res);
1836 return;
1837 }
1838 },
1839 "xyz.openbmc_project.Settings",
1840 "/xyz/openbmc_project/control/host0/auto_reboot",
1841 "org.freedesktop.DBus.Properties", "Set",
1842 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1843 std::variant<bool>(autoRebootEnabled));
1844}
1845
1846/**
George Liuc6a620f2020-04-10 17:18:11 +08001847 * @brief Sets power restore policy properties.
1848 *
1849 * @param[in] aResp Shared pointer for generating response message.
1850 * @param[in] policy power restore policy properties from request.
1851 *
1852 * @return None.
1853 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001854inline void
1855 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1856 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001857{
1858 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1859
1860 const boost::container::flat_map<std::string, std::string> policyMaps = {
1861 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1862 "AlwaysOn"},
1863 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1864 "AlwaysOff"},
1865 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001866 "Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001867
1868 std::string powerRestorPolicy;
1869
Gunnar Mills4e69c902021-01-05 19:50:11 -06001870 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001871 if (policyMapsIt == policyMaps.end())
1872 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001873 messages::propertyValueNotInList(aResp->res, policy,
1874 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001875 return;
1876 }
1877
1878 powerRestorPolicy = policyMapsIt->second;
1879
1880 crow::connections::systemBus->async_method_call(
1881 [aResp](const boost::system::error_code ec) {
1882 if (ec)
1883 {
1884 messages::internalError(aResp->res);
1885 return;
1886 }
1887 },
1888 "xyz.openbmc_project.Settings",
1889 "/xyz/openbmc_project/control/host0/power_restore_policy",
1890 "org.freedesktop.DBus.Properties", "Set",
1891 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1892 std::variant<std::string>(powerRestorPolicy));
1893}
1894
AppaRao Pulia6349912019-10-18 17:16:08 +05301895#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1896/**
1897 * @brief Retrieves provisioning status
1898 *
1899 * @param[in] aResp Shared pointer for completing asynchronous calls.
1900 *
1901 * @return None.
1902 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001903inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301904{
1905 BMCWEB_LOG_DEBUG << "Get OEM information.";
1906 crow::connections::systemBus->async_method_call(
1907 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001908 const std::vector<std::pair<std::string, VariantType>>&
1909 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301910 nlohmann::json& oemPFR =
1911 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001912 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1913 "#OemComputerSystem.OpenBmc";
1914 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1915
AppaRao Pulia6349912019-10-18 17:16:08 +05301916 if (ec)
1917 {
1918 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301919 // not an error, don't have to have the interface
1920 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301921 return;
1922 }
1923
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001924 const bool* provState = nullptr;
1925 const bool* lockState = nullptr;
1926 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301927 propertiesList)
1928 {
1929 if (property.first == "UfmProvisioned")
1930 {
1931 provState = std::get_if<bool>(&property.second);
1932 }
1933 else if (property.first == "UfmLocked")
1934 {
1935 lockState = std::get_if<bool>(&property.second);
1936 }
1937 }
1938
1939 if ((provState == nullptr) || (lockState == nullptr))
1940 {
1941 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1942 messages::internalError(aResp->res);
1943 return;
1944 }
1945
AppaRao Pulia6349912019-10-18 17:16:08 +05301946 if (*provState == true)
1947 {
1948 if (*lockState == true)
1949 {
1950 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1951 }
1952 else
1953 {
1954 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1955 }
1956 }
1957 else
1958 {
1959 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1960 }
1961 },
1962 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1963 "org.freedesktop.DBus.Properties", "GetAll",
1964 "xyz.openbmc_project.PFR.Attributes");
1965}
1966#endif
1967
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301968/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001969 * @brief Translate the PowerMode to a response message.
1970 *
1971 * @param[in] aResp Shared pointer for generating response message.
1972 * @param[in] modeValue PowerMode value to be translated
1973 *
1974 * @return None.
1975 */
1976inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1977 const std::string& modeValue)
1978{
1979 std::string modeString;
1980
1981 if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1982 "PowerMode.Static")
1983 {
1984 aResp->res.jsonValue["PowerMode"] = "Static";
1985 }
1986 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1987 "PowerMode.MaximumPerformance")
1988 {
1989 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1990 }
1991 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1992 "PowerMode.PowerSaving")
1993 {
1994 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1995 }
1996 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1997 "PowerMode.OEM")
1998 {
1999 aResp->res.jsonValue["PowerMode"] = "OEM";
2000 }
2001 else
2002 {
2003 // Any other values would be invalid
2004 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2005 messages::internalError(aResp->res);
2006 }
2007}
2008
2009/**
2010 * @brief Retrieves system power mode
2011 *
2012 * @param[in] aResp Shared pointer for generating response message.
2013 *
2014 * @return None.
2015 */
2016inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2017{
2018 BMCWEB_LOG_DEBUG << "Get power mode.";
2019
2020 // Get Power Mode object path:
2021 crow::connections::systemBus->async_method_call(
2022 [aResp](
2023 const boost::system::error_code ec,
2024 const std::vector<std::pair<
2025 std::string,
2026 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2027 subtree) {
2028 if (ec)
2029 {
2030 BMCWEB_LOG_DEBUG
2031 << "DBUS response error on Power.Mode GetSubTree " << ec;
2032 // This is an optional D-Bus object so just return if
2033 // error occurs
2034 return;
2035 }
2036 if (subtree.empty())
2037 {
2038 // As noted above, this is an optional interface so just return
2039 // if there is no instance found
2040 return;
2041 }
2042 if (subtree.size() > 1)
2043 {
2044 // More then one PowerMode object is not supported and is an
2045 // error
2046 BMCWEB_LOG_DEBUG
2047 << "Found more than 1 system D-Bus Power.Mode objects: "
2048 << subtree.size();
2049 messages::internalError(aResp->res);
2050 return;
2051 }
2052 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2053 {
2054 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2055 messages::internalError(aResp->res);
2056 return;
2057 }
2058 const std::string& path = subtree[0].first;
2059 const std::string& service = subtree[0].second.begin()->first;
2060 if (service.empty())
2061 {
2062 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2063 messages::internalError(aResp->res);
2064 return;
2065 }
2066 // Valid Power Mode object found, now read the current value
2067 crow::connections::systemBus->async_method_call(
2068 [aResp](const boost::system::error_code ec,
2069 const std::variant<std::string>& pmode) {
2070 if (ec)
2071 {
2072 BMCWEB_LOG_DEBUG
2073 << "DBUS response error on PowerMode Get: " << ec;
2074 messages::internalError(aResp->res);
2075 return;
2076 }
2077
2078 const std::string* s = std::get_if<std::string>(&pmode);
2079 if (s == nullptr)
2080 {
2081 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2082 messages::internalError(aResp->res);
2083 return;
2084 }
2085
2086 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2087 {"Static", "MaximumPerformance", "PowerSaving"};
2088
2089 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2090 translatePowerMode(aResp, *s);
2091 },
2092 service, path, "org.freedesktop.DBus.Properties", "Get",
2093 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2094 },
2095 "xyz.openbmc_project.ObjectMapper",
2096 "/xyz/openbmc_project/object_mapper",
2097 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2098 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2099}
2100
2101/**
2102 * @brief Validate the specified mode is valid and return the PowerMode
2103 * name associated with that string
2104 *
2105 * @param[in] aResp Shared pointer for generating response message.
2106 * @param[in] modeString String representing the desired PowerMode
2107 *
2108 * @return PowerMode value or empty string if mode is not valid
2109 */
2110inline std::string
2111 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2112 const std::string& modeString)
2113{
2114 std::string mode;
2115
2116 if (modeString == "Static")
2117 {
2118 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2119 }
2120 else if (modeString == "MaximumPerformance")
2121 {
2122 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
2123 "MaximumPerformance";
2124 }
2125 else if (modeString == "PowerSaving")
2126 {
2127 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2128 }
2129 else
2130 {
2131 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2132 }
2133 return mode;
2134}
2135
2136/**
2137 * @brief Sets system power mode.
2138 *
2139 * @param[in] aResp Shared pointer for generating response message.
2140 * @param[in] pmode System power mode from request.
2141 *
2142 * @return None.
2143 */
2144inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2145 const std::string& pmode)
2146{
2147 BMCWEB_LOG_DEBUG << "Set power mode.";
2148
2149 std::string powerMode = validatePowerMode(aResp, pmode);
2150 if (powerMode.empty())
2151 {
2152 return;
2153 }
2154
2155 // Get Power Mode object path:
2156 crow::connections::systemBus->async_method_call(
2157 [aResp, powerMode](
2158 const boost::system::error_code ec,
2159 const std::vector<std::pair<
2160 std::string,
2161 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2162 subtree) {
2163 if (ec)
2164 {
2165 BMCWEB_LOG_DEBUG
2166 << "DBUS response error on Power.Mode GetSubTree " << ec;
2167 // This is an optional D-Bus object, but user attempted to patch
2168 messages::internalError(aResp->res);
2169 return;
2170 }
2171 if (subtree.empty())
2172 {
2173 // This is an optional D-Bus object, but user attempted to patch
2174 messages::resourceNotFound(aResp->res, "ComputerSystem",
2175 "PowerMode");
2176 return;
2177 }
2178 if (subtree.size() > 1)
2179 {
2180 // More then one PowerMode object is not supported and is an
2181 // error
2182 BMCWEB_LOG_DEBUG
2183 << "Found more than 1 system D-Bus Power.Mode objects: "
2184 << subtree.size();
2185 messages::internalError(aResp->res);
2186 return;
2187 }
2188 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2189 {
2190 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2191 messages::internalError(aResp->res);
2192 return;
2193 }
2194 const std::string& path = subtree[0].first;
2195 const std::string& service = subtree[0].second.begin()->first;
2196 if (service.empty())
2197 {
2198 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2199 messages::internalError(aResp->res);
2200 return;
2201 }
2202
2203 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2204 << path;
2205
2206 // Set the Power Mode property
2207 crow::connections::systemBus->async_method_call(
2208 [aResp](const boost::system::error_code ec) {
2209 if (ec)
2210 {
2211 messages::internalError(aResp->res);
2212 return;
2213 }
2214 },
2215 service, path, "org.freedesktop.DBus.Properties", "Set",
2216 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2217 std::variant<std::string>(powerMode));
2218 },
2219 "xyz.openbmc_project.ObjectMapper",
2220 "/xyz/openbmc_project/object_mapper",
2221 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2222 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2223}
2224
2225/**
Yong Li51709ff2019-09-30 14:13:04 +08002226 * @brief Translates watchdog timeout action DBUS property value to redfish.
2227 *
2228 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2229 *
2230 * @return Returns as a string, the timeout action in Redfish terms. If
2231 * translation cannot be done, returns an empty string.
2232 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002233inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002234{
2235 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2236 {
2237 return "None";
2238 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002239 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002240 {
2241 return "ResetSystem";
2242 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002243 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002244 {
2245 return "PowerDown";
2246 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002247 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002248 {
2249 return "PowerCycle";
2250 }
2251
2252 return "";
2253}
2254
2255/**
Yong Lic45f0082019-10-10 14:19:01 +08002256 *@brief Translates timeout action from Redfish to DBUS property value.
2257 *
2258 *@param[in] rfAction The timeout action in Redfish.
2259 *
2260 *@return Returns as a string, the time_out action as expected by DBUS.
2261 *If translation cannot be done, returns an empty string.
2262 */
2263
Ed Tanous23a21a12020-07-25 04:45:05 +00002264inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002265{
2266 if (rfAction == "None")
2267 {
2268 return "xyz.openbmc_project.State.Watchdog.Action.None";
2269 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002270 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002271 {
2272 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2273 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002274 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002275 {
2276 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2277 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002278 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002279 {
2280 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2281 }
2282
2283 return "";
2284}
2285
2286/**
Yong Li51709ff2019-09-30 14:13:04 +08002287 * @brief Retrieves host watchdog timer properties over DBUS
2288 *
2289 * @param[in] aResp Shared pointer for completing asynchronous calls.
2290 *
2291 * @return None.
2292 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002293inline void
2294 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002295{
2296 BMCWEB_LOG_DEBUG << "Get host watchodg";
2297 crow::connections::systemBus->async_method_call(
2298 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002299 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002300 if (ec)
2301 {
2302 // watchdog service is stopped
2303 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2304 return;
2305 }
2306
2307 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2308
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002309 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002310 aResp->res.jsonValue["HostWatchdogTimer"];
2311
2312 // watchdog service is running/enabled
2313 hostWatchdogTimer["Status"]["State"] = "Enabled";
2314
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002315 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002316 {
2317 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2318 if (property.first == "Enabled")
2319 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002320 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002321
2322 if (!state)
2323 {
2324 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002325 return;
Yong Li51709ff2019-09-30 14:13:04 +08002326 }
2327
2328 hostWatchdogTimer["FunctionEnabled"] = *state;
2329 }
2330 else if (property.first == "ExpireAction")
2331 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002332 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002333 std::get_if<std::string>(&property.second);
2334 if (!s)
2335 {
2336 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002337 return;
Yong Li51709ff2019-09-30 14:13:04 +08002338 }
2339
2340 std::string action = dbusToRfWatchdogAction(*s);
2341 if (action.empty())
2342 {
2343 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002344 return;
Yong Li51709ff2019-09-30 14:13:04 +08002345 }
2346 hostWatchdogTimer["TimeoutAction"] = action;
2347 }
2348 }
2349 },
2350 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2351 "org.freedesktop.DBus.Properties", "GetAll",
2352 "xyz.openbmc_project.State.Watchdog");
2353}
2354
2355/**
Yong Lic45f0082019-10-10 14:19:01 +08002356 * @brief Sets Host WatchDog Timer properties.
2357 *
2358 * @param[in] aResp Shared pointer for generating response message.
2359 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2360 * RF request.
2361 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2362 *
2363 * @return None.
2364 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002365inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002366 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002367 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002368{
2369 BMCWEB_LOG_DEBUG << "Set host watchdog";
2370
2371 if (wdtTimeOutAction)
2372 {
2373 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2374 // check if TimeOut Action is Valid
2375 if (wdtTimeOutActStr.empty())
2376 {
2377 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2378 << *wdtTimeOutAction;
2379 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2380 "TimeoutAction");
2381 return;
2382 }
2383
2384 crow::connections::systemBus->async_method_call(
2385 [aResp](const boost::system::error_code ec) {
2386 if (ec)
2387 {
2388 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2389 messages::internalError(aResp->res);
2390 return;
2391 }
2392 },
2393 "xyz.openbmc_project.Watchdog",
2394 "/xyz/openbmc_project/watchdog/host0",
2395 "org.freedesktop.DBus.Properties", "Set",
2396 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2397 std::variant<std::string>(wdtTimeOutActStr));
2398 }
2399
2400 if (wdtEnable)
2401 {
2402 crow::connections::systemBus->async_method_call(
2403 [aResp](const boost::system::error_code ec) {
2404 if (ec)
2405 {
2406 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2407 messages::internalError(aResp->res);
2408 return;
2409 }
2410 },
2411 "xyz.openbmc_project.Watchdog",
2412 "/xyz/openbmc_project/watchdog/host0",
2413 "org.freedesktop.DBus.Properties", "Set",
2414 "xyz.openbmc_project.State.Watchdog", "Enabled",
2415 std::variant<bool>(*wdtEnable));
2416 }
2417}
2418
2419/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002420 * SystemsCollection derived class for delivering ComputerSystems Collection
2421 * Schema
2422 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002423inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002424{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002425 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002426 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002427 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002428 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002429 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2430 asyncResp->res.jsonValue["@odata.type"] =
2431 "#ComputerSystemCollection.ComputerSystemCollection";
2432 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2433 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002434
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002435 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002436 [asyncResp](const boost::system::error_code ec,
2437 const std::variant<std::string>& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002438 nlohmann::json& ifaceArray =
2439 asyncResp->res.jsonValue["Members"];
2440 ifaceArray = nlohmann::json::array();
2441 auto& count =
2442 asyncResp->res.jsonValue["Members@odata.count"];
2443 ifaceArray.push_back(
2444 {{"@odata.id", "/redfish/v1/Systems/system"}});
2445 count = ifaceArray.size();
2446 if (!ec)
2447 {
2448 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2449 ifaceArray.push_back(
2450 {{"@odata.id",
2451 "/redfish/v1/Systems/hypervisor"}});
2452 count = ifaceArray.size();
2453 }
2454 },
2455 "xyz.openbmc_project.Settings",
2456 "/xyz/openbmc_project/network/hypervisor",
2457 "org.freedesktop.DBus.Properties", "Get",
2458 "xyz.openbmc_project.Network.SystemConfiguration",
2459 "HostName");
2460 });
2461}
Sunitha Harish462023a2020-02-19 08:34:59 -06002462
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002463/**
2464 * Function transceives data with dbus directly.
2465 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002466inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002467{
2468 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2469 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2470 constexpr char const* interfaceName =
2471 "xyz.openbmc_project.Control.Host.NMI";
2472 constexpr char const* method = "NMI";
2473
2474 crow::connections::systemBus->async_method_call(
2475 [asyncResp](const boost::system::error_code ec) {
2476 if (ec)
2477 {
2478 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2479 messages::internalError(asyncResp->res);
2480 return;
2481 }
2482 messages::success(asyncResp->res);
2483 },
2484 serviceName, objectPath, interfaceName, method);
2485}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002486
2487/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002488 * SystemActionsReset class supports handle POST method for Reset action.
2489 * The class retrieves and sends data directly to D-Bus.
2490 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002491inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002492{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002493 /**
2494 * Function handles POST method request.
2495 * Analyzes POST body message before sends Reset request data to D-Bus.
2496 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002497 BMCWEB_ROUTE(app,
2498 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002499 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002500 .methods(
2501 boost::beast::http::verb::
2502 post)([](const crow::Request& req,
2503 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2504 std::string resetType;
2505 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2506 resetType))
2507 {
2508 return;
2509 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002510
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002511 // Get the command and host vs. chassis
2512 std::string command;
2513 bool hostCommand;
2514 if ((resetType == "On") || (resetType == "ForceOn"))
2515 {
2516 command = "xyz.openbmc_project.State.Host.Transition.On";
2517 hostCommand = true;
2518 }
2519 else if (resetType == "ForceOff")
2520 {
2521 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2522 hostCommand = false;
2523 }
2524 else if (resetType == "ForceRestart")
2525 {
2526 command =
2527 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2528 hostCommand = true;
2529 }
2530 else if (resetType == "GracefulShutdown")
2531 {
2532 command = "xyz.openbmc_project.State.Host.Transition.Off";
2533 hostCommand = true;
2534 }
2535 else if (resetType == "GracefulRestart")
2536 {
2537 command = "xyz.openbmc_project.State.Host.Transition."
2538 "GracefulWarmReboot";
2539 hostCommand = true;
2540 }
2541 else if (resetType == "PowerCycle")
2542 {
2543 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2544 hostCommand = true;
2545 }
2546 else if (resetType == "Nmi")
2547 {
2548 doNMI(asyncResp);
2549 return;
2550 }
2551 else
2552 {
2553 messages::actionParameterUnknown(asyncResp->res, "Reset",
2554 resetType);
2555 return;
2556 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002557
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002558 if (hostCommand)
2559 {
2560 crow::connections::systemBus->async_method_call(
2561 [asyncResp, resetType](const boost::system::error_code ec) {
2562 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002563 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002564 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2565 if (ec.value() ==
2566 boost::asio::error::invalid_argument)
2567 {
2568 messages::actionParameterNotSupported(
2569 asyncResp->res, resetType, "Reset");
2570 }
2571 else
2572 {
2573 messages::internalError(asyncResp->res);
2574 }
2575 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002576 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002577 messages::success(asyncResp->res);
2578 },
2579 "xyz.openbmc_project.State.Host",
2580 "/xyz/openbmc_project/state/host0",
2581 "org.freedesktop.DBus.Properties", "Set",
2582 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2583 std::variant<std::string>{command});
2584 }
2585 else
2586 {
2587 crow::connections::systemBus->async_method_call(
2588 [asyncResp, resetType](const boost::system::error_code ec) {
2589 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002590 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002591 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2592 if (ec.value() ==
2593 boost::asio::error::invalid_argument)
2594 {
2595 messages::actionParameterNotSupported(
2596 asyncResp->res, resetType, "Reset");
2597 }
2598 else
2599 {
2600 messages::internalError(asyncResp->res);
2601 }
2602 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002603 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002604 messages::success(asyncResp->res);
2605 },
2606 "xyz.openbmc_project.State.Chassis",
2607 "/xyz/openbmc_project/state/chassis0",
2608 "org.freedesktop.DBus.Properties", "Set",
2609 "xyz.openbmc_project.State.Chassis",
2610 "RequestedPowerTransition",
2611 std::variant<std::string>{command});
2612 }
2613 });
2614}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002615
2616/**
Ed Tanous66173382018-08-15 18:20:59 -07002617 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002618 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002619inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002620{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002621
Ed Tanous1abe55e2018-09-05 08:30:59 -07002622 /**
2623 * Functions triggers appropriate requests on DBus
2624 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002625 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002626 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002627 .methods(
2628 boost::beast::http::verb::
2629 get)([](const crow::Request&,
2630 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2631 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain3a2d04242021-05-28 16:57:10 -05002632 "#ComputerSystem.v1_15_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002633 asyncResp->res.jsonValue["Name"] = "system";
2634 asyncResp->res.jsonValue["Id"] = "system";
2635 asyncResp->res.jsonValue["SystemType"] = "Physical";
2636 asyncResp->res.jsonValue["Description"] = "Computer System";
2637 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2638 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2639 "Disabled";
2640 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2641 uint64_t(0);
2642 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2643 "Disabled";
2644 asyncResp->res.jsonValue["@odata.id"] =
2645 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002646
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002647 asyncResp->res.jsonValue["Processors"] = {
2648 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2649 asyncResp->res.jsonValue["Memory"] = {
2650 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2651 asyncResp->res.jsonValue["Storage"] = {
2652 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002653
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002654 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2655 {"target",
2656 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2657 {"@Redfish.ActionInfo",
2658 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002659
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002660 asyncResp->res.jsonValue["LogServices"] = {
2661 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002662
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002663 asyncResp->res.jsonValue["Bios"] = {
2664 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002665
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002666 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2667 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002668
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002669 asyncResp->res.jsonValue["Status"] = {
2670 {"Health", "OK"},
2671 {"State", "Enabled"},
2672 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002673
2674 // Fill in SerialConsole info
2675 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2676 15;
2677 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2678 {"ServiceEnabled", true},
2679 };
2680 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2681 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2682 {"ServiceEnabled", true},
2683 {"Port", 2200},
2684 // https://github.com/openbmc/docs/blob/master/console.md
2685 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2686 };
2687
2688#ifdef BMCWEB_ENABLE_KVM
2689 // Fill in GraphicalConsole info
2690 asyncResp->res.jsonValue["GraphicalConsole"] = {
2691 {"ServiceEnabled", true},
2692 {"MaxConcurrentSessions", 4},
2693 {"ConnectTypesSupported", {"KVMIP"}},
2694 };
2695#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002696 constexpr const std::array<const char*, 4> inventoryForSystems = {
2697 "xyz.openbmc_project.Inventory.Item.Dimm",
2698 "xyz.openbmc_project.Inventory.Item.Cpu",
2699 "xyz.openbmc_project.Inventory.Item.Drive",
2700 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002701
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002702 auto health = std::make_shared<HealthPopulate>(asyncResp);
2703 crow::connections::systemBus->async_method_call(
2704 [health](const boost::system::error_code ec,
2705 std::vector<std::string>& resp) {
2706 if (ec)
2707 {
2708 // no inventory
2709 return;
2710 }
2711
2712 health->inventory = std::move(resp);
2713 },
2714 "xyz.openbmc_project.ObjectMapper",
2715 "/xyz/openbmc_project/object_mapper",
2716 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2717 int32_t(0), inventoryForSystems);
2718
2719 health->populate();
2720
2721 getMainChassisId(
2722 asyncResp, [](const std::string& chassisId,
2723 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2724 aRsp->res.jsonValue["Links"]["Chassis"] = {
2725 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2726 });
2727
2728 getLocationIndicatorActive(asyncResp);
2729 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2730 getIndicatorLedState(asyncResp);
2731 getComputerSystem(asyncResp, health);
2732 getHostState(asyncResp);
2733 getBootProperties(asyncResp);
2734 getBootProgress(asyncResp);
2735 getPCIeDeviceList(asyncResp, "PCIeDevices");
2736 getHostWatchdogTimer(asyncResp);
2737 getPowerRestorePolicy(asyncResp);
2738 getAutomaticRetry(asyncResp);
2739 getLastResetTime(asyncResp);
2740#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2741 getProvisioningStatus(asyncResp);
2742#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002743 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002744 getPowerMode(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002745 });
2746 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002747 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002748 .methods(boost::beast::http::verb::patch)(
2749 [](const crow::Request& req,
2750 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2751 std::optional<bool> locationIndicatorActive;
2752 std::optional<std::string> indicatorLed;
2753 std::optional<nlohmann::json> bootProps;
2754 std::optional<nlohmann::json> wdtTimerProps;
2755 std::optional<std::string> assetTag;
2756 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002757 std::optional<std::string> powerMode;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002758
2759 if (!json_util::readJson(
2760 req, asyncResp->res, "IndicatorLED", indicatorLed,
2761 "LocationIndicatorActive", locationIndicatorActive,
2762 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2763 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain3a2d04242021-05-28 16:57:10 -05002764 assetTag, "PowerMode", powerMode))
James Feistb49ac872019-05-21 15:12:01 -07002765 {
James Feistb49ac872019-05-21 15:12:01 -07002766 return;
2767 }
2768
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002769 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07002770
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002771 if (assetTag)
2772 {
2773 setAssetTag(asyncResp, *assetTag);
2774 }
James Feistb49ac872019-05-21 15:12:01 -07002775
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002776 if (wdtTimerProps)
2777 {
2778 std::optional<bool> wdtEnable;
2779 std::optional<std::string> wdtTimeOutAction;
2780
2781 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
2782 "FunctionEnabled", wdtEnable,
2783 "TimeoutAction", wdtTimeOutAction))
2784 {
2785 return;
2786 }
2787 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
2788 }
2789
2790 if (bootProps)
2791 {
2792 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002793 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002794 std::optional<std::string> bootEnable;
2795 std::optional<std::string> automaticRetryConfig;
2796
2797 if (!json_util::readJson(
2798 *bootProps, asyncResp->res,
2799 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002800 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002801 "BootSourceOverrideEnabled", bootEnable,
2802 "AutomaticRetryConfig", automaticRetryConfig))
2803 {
2804 return;
2805 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002806 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002807 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002808 setBootSourceProperties(
2809 asyncResp, std::move(bootSource),
2810 std::move(bootType), std::move(bootEnable));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002811 }
2812 if (automaticRetryConfig)
2813 {
2814 setAutomaticRetry(asyncResp, *automaticRetryConfig);
2815 }
2816 }
2817
2818 if (locationIndicatorActive)
2819 {
2820 setLocationIndicatorActive(asyncResp,
2821 *locationIndicatorActive);
2822 }
2823
2824 // TODO (Gunnar): Remove IndicatorLED after enough time has
2825 // passed
2826 if (indicatorLed)
2827 {
2828 setIndicatorLedState(asyncResp, *indicatorLed);
2829 asyncResp->res.addHeader(
2830 boost::beast::http::field::warning,
2831 "299 - \"IndicatorLED is deprecated. Use "
2832 "LocationIndicatorActive instead.\"");
2833 }
2834
2835 if (powerRestorePolicy)
2836 {
2837 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
2838 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002839
2840 if (powerMode)
2841 {
2842 setPowerMode(asyncResp, *powerMode);
2843 }
zhanghch058d1b46d2021-04-01 11:18:24 +08002844 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002845}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302846
2847/**
2848 * SystemResetActionInfo derived class for delivering Computer Systems
2849 * ResetType AllowableValues using ResetInfo schema.
2850 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002851inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302852{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302853
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302854 /**
2855 * Functions triggers appropriate requests on DBus
2856 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002857 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07002858 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002859 .methods(boost::beast::http::verb::get)(
2860 [](const crow::Request&,
2861 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2862 asyncResp->res.jsonValue = {
2863 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
2864 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
2865 {"Name", "Reset Action Info"},
2866 {"Id", "ResetActionInfo"},
2867 {"Parameters",
2868 {{{"Name", "ResetType"},
2869 {"Required", true},
2870 {"DataType", "String"},
2871 {"AllowableValues",
2872 {"On", "ForceOff", "ForceOn", "ForceRestart",
2873 "GracefulRestart", "GracefulShutdown", "PowerCycle",
2874 "Nmi"}}}}}};
2875 });
2876}
Ed Tanous1abe55e2018-09-05 08:30:59 -07002877} // namespace redfish