blob: 320f4e4f26c53b07ed65ba88e1bc627b03861669 [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{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300772 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
773 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700774
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530775 if (rfSource == "None")
776 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700777 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700779 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700781 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
782 }
783 else if (rfSource == "Hdd")
784 {
785 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
786 }
787 else if (rfSource == "Diags")
788 {
789 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
790 }
791 else if (rfSource == "Cd")
792 {
793 bootSource =
794 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
795 }
796 else if (rfSource == "BiosSetup")
797 {
798 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530799 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700800 else if (rfSource == "Usb")
801 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700802 bootSource =
803 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700804 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530805 else
806 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700807 BMCWEB_LOG_DEBUG << "Invalid property value for "
808 "BootSourceOverrideTarget: "
809 << bootSource;
810 messages::propertyValueNotInList(aResp->res, rfSource,
811 "BootSourceTargetOverride");
812 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530813 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700814 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530815}
Ali Ahmed19817712021-06-29 17:01:52 -0500816
Andrew Geissler978b8802020-11-19 13:36:40 -0600817/**
818 * @brief Retrieves boot progress of the system
819 *
820 * @param[in] aResp Shared pointer for generating response message.
821 *
822 * @return None.
823 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800824inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600825{
826 crow::connections::systemBus->async_method_call(
827 [aResp](const boost::system::error_code ec,
828 const std::variant<std::string>& bootProgress) {
829 if (ec)
830 {
831 // BootProgress is an optional object so just do nothing if
832 // not found
833 return;
834 }
835
836 const std::string* bootProgressStr =
837 std::get_if<std::string>(&bootProgress);
838
839 if (!bootProgressStr)
840 {
841 // Interface implemented but property not found, return error
842 // for that
843 messages::internalError(aResp->res);
844 return;
845 }
846
847 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
848
849 // Now convert the D-Bus BootProgress to the appropriate Redfish
850 // enum
851 std::string rfBpLastState = "None";
852 if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
853 "ProgressStages.Unspecified")
854 {
855 rfBpLastState = "None";
856 }
857 else if (*bootProgressStr ==
858 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
859 "PrimaryProcInit")
860 {
861 rfBpLastState = "PrimaryProcessorInitializationStarted";
862 }
863 else if (*bootProgressStr ==
864 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
865 "BusInit")
866 {
867 rfBpLastState = "BusInitializationStarted";
868 }
869 else if (*bootProgressStr ==
870 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
871 "MemoryInit")
872 {
873 rfBpLastState = "MemoryInitializationStarted";
874 }
875 else if (*bootProgressStr ==
876 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
877 "SecondaryProcInit")
878 {
879 rfBpLastState = "SecondaryProcessorInitializationStarted";
880 }
881 else if (*bootProgressStr ==
882 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
883 "PCIInit")
884 {
885 rfBpLastState = "PCIResourceConfigStarted";
886 }
887 else if (*bootProgressStr ==
888 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
889 "SystemInitComplete")
890 {
891 rfBpLastState = "SystemHardwareInitializationComplete";
892 }
893 else if (*bootProgressStr ==
894 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
895 "OSStart")
896 {
897 rfBpLastState = "OSBootStarted";
898 }
899 else if (*bootProgressStr ==
900 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
901 "OSRunning")
902 {
903 rfBpLastState = "OSRunning";
904 }
905 else
906 {
907 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
908 << *bootProgressStr;
909 // Just return the default
910 }
911
912 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
913 },
914 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
915 "org.freedesktop.DBus.Properties", "Get",
916 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
917}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530918
919/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300920 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300921 *
922 * @param[in] aResp Shared pointer for generating response message.
923 *
924 * @return None.
925 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300926
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300927inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300928{
929 crow::connections::systemBus->async_method_call(
930 [aResp](const boost::system::error_code ec,
931 const std::variant<std::string>& bootType) {
932 if (ec)
933 {
934 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300935 return;
936 }
937
938 const std::string* bootTypeStr =
939 std::get_if<std::string>(&bootType);
940
941 if (!bootTypeStr)
942 {
943 messages::internalError(aResp->res);
944 return;
945 }
946
947 BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
948
949 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode@Redfish."
950 "AllowableValues"] = {"Legacy",
951 "UEFI"};
952
953 auto rfType = dbusToRfBootType(*bootTypeStr);
954 if (rfType.empty())
955 {
956 messages::internalError(aResp->res);
957 return;
958 }
959
960 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300961 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300962 "xyz.openbmc_project.Settings",
963 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300964 "org.freedesktop.DBus.Properties", "Get",
965 "xyz.openbmc_project.Control.Boot.Type", "BootType");
966}
967
968/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300969 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530970 *
971 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530972 *
973 * @return None.
974 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300975
976inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530977{
978 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300979 [aResp](const boost::system::error_code ec,
980 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530981 if (ec)
982 {
983 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
984 messages::internalError(aResp->res);
985 return;
986 }
987
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500988 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530989 std::get_if<std::string>(&bootMode);
990
991 if (!bootModeStr)
992 {
993 messages::internalError(aResp->res);
994 return;
995 }
996
997 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
998
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530999 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
1000 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001001 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301002
1003 if (*bootModeStr !=
1004 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1005 {
1006 auto rfMode = dbusToRfBootMode(*bootModeStr);
1007 if (!rfMode.empty())
1008 {
1009 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1010 rfMode;
1011 }
1012 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301013 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001014 "xyz.openbmc_project.Settings",
1015 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301016 "org.freedesktop.DBus.Properties", "Get",
1017 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
1018}
1019
1020/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001021 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022 *
1023 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301024 *
1025 * @return None.
1026 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001027
1028inline void
1029 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301030{
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301031 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001032 [aResp](const boost::system::error_code ec,
1033 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034 if (ec)
1035 {
1036 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1037 messages::internalError(aResp->res);
1038 return;
1039 }
1040
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001041 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301042 std::get_if<std::string>(&bootSource);
1043
1044 if (!bootSourceStr)
1045 {
1046 messages::internalError(aResp->res);
1047 return;
1048 }
1049 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1050
1051 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1052 if (!rfSource.empty())
1053 {
1054 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1055 rfSource;
1056 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001057
1058 // Get BootMode as BootSourceOverrideTarget is constructed
1059 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001060 getBootOverrideMode(aResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301061 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001062 "xyz.openbmc_project.Settings",
1063 "/xyz/openbmc_project/control/host0/boot",
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301064 "org.freedesktop.DBus.Properties", "Get",
1065 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301066}
1067
1068/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001069 * @brief This functions abstracts all the logic behind getting a
1070 * "BootSourceOverrideEnabled" property from an overall boot override enable
1071 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301072 *
1073 * @param[in] aResp Shared pointer for generating response message.
1074 *
1075 * @return None.
1076 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301077
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001078inline void
1079 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1080 const bool bootOverrideEnableSetting)
1081{
1082 if (!bootOverrideEnableSetting)
1083 {
1084 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1085 return;
1086 }
1087
1088 // If boot source override is enabled, we need to check 'one_time'
1089 // property to set a correct value for the "BootSourceOverrideEnabled"
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301090 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001091 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001092 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301093 if (ec)
1094 {
1095 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001096 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301097 return;
1098 }
1099
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001100 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301101
1102 if (!oneTimePtr)
1103 {
1104 messages::internalError(aResp->res);
1105 return;
1106 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001107
1108 bool oneTimeSetting = *oneTimePtr;
1109
1110 if (oneTimeSetting)
1111 {
1112 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1113 "Once";
1114 }
1115 else
1116 {
1117 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1118 "Continuous";
1119 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301120 },
1121 "xyz.openbmc_project.Settings",
1122 "/xyz/openbmc_project/control/host0/boot/one_time",
1123 "org.freedesktop.DBus.Properties", "Get",
1124 "xyz.openbmc_project.Object.Enable", "Enabled");
1125}
1126
1127/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001128 * @brief Retrieves boot override enable over DBUS
1129 *
1130 * @param[in] aResp Shared pointer for generating response message.
1131 *
1132 * @return None.
1133 */
1134
1135inline void
1136 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1137{
1138 crow::connections::systemBus->async_method_call(
1139 [aResp](const boost::system::error_code ec,
1140 const std::variant<bool>& bootOverrideEnable) {
1141 if (ec)
1142 {
1143 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1144 messages::internalError(aResp->res);
1145 return;
1146 }
1147
1148 const bool* bootOverrideEnablePtr =
1149 std::get_if<bool>(&bootOverrideEnable);
1150
1151 if (!bootOverrideEnablePtr)
1152 {
1153 messages::internalError(aResp->res);
1154 return;
1155 }
1156
1157 processBootOverrideEnable(aResp, *bootOverrideEnablePtr);
1158 },
1159 "xyz.openbmc_project.Settings",
1160 "/xyz/openbmc_project/control/host0/boot",
1161 "org.freedesktop.DBus.Properties", "Get",
1162 "xyz.openbmc_project.Object.Enable", "Enabled");
1163}
1164
1165/**
1166 * @brief Retrieves boot source override properties
1167 *
1168 * @param[in] aResp Shared pointer for generating response message.
1169 *
1170 * @return None.
1171 */
1172inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1173{
1174 BMCWEB_LOG_DEBUG << "Get boot information.";
1175
1176 getBootOverrideSource(aResp);
1177 getBootOverrideType(aResp);
1178 getBootOverrideEnable(aResp);
1179}
1180
1181/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001182 * @brief Retrieves the Last Reset Time
1183 *
1184 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1185 * and power off. Even though this is the "system" Redfish object look at the
1186 * chassis D-Bus interface for the LastStateChangeTime since this has the
1187 * last power operation time.
1188 *
1189 * @param[in] aResp Shared pointer for generating response message.
1190 *
1191 * @return None.
1192 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001193inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001194{
1195 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1196
1197 crow::connections::systemBus->async_method_call(
1198 [aResp](const boost::system::error_code ec,
1199 std::variant<uint64_t>& lastResetTime) {
1200 if (ec)
1201 {
1202 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1203 return;
1204 }
1205
1206 const uint64_t* lastResetTimePtr =
1207 std::get_if<uint64_t>(&lastResetTime);
1208
1209 if (!lastResetTimePtr)
1210 {
1211 messages::internalError(aResp->res);
1212 return;
1213 }
1214 // LastStateChangeTime is epoch time, in milliseconds
1215 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1216 time_t lastResetTimeStamp =
1217 static_cast<time_t>(*lastResetTimePtr / 1000);
1218
1219 // Convert to ISO 8601 standard
1220 aResp->res.jsonValue["LastResetTime"] =
1221 crow::utility::getDateTime(lastResetTimeStamp);
1222 },
1223 "xyz.openbmc_project.State.Chassis",
1224 "/xyz/openbmc_project/state/chassis0",
1225 "org.freedesktop.DBus.Properties", "Get",
1226 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1227}
1228
1229/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001230 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1231 *
1232 * @param[in] aResp Shared pointer for generating response message.
1233 *
1234 * @return None.
1235 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001236inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001237{
1238 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1239
1240 crow::connections::systemBus->async_method_call(
1241 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001242 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001243 if (ec)
1244 {
1245 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1246 return;
1247 }
1248
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001249 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001250 std::get_if<bool>(&autoRebootEnabled);
1251
1252 if (!autoRebootEnabledPtr)
1253 {
1254 messages::internalError(aResp->res);
1255 return;
1256 }
1257
1258 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1259 if (*autoRebootEnabledPtr == true)
1260 {
1261 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1262 "RetryAttempts";
1263 // If AutomaticRetry (AutoReboot) is enabled see how many
1264 // attempts are left
1265 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001266 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001267 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001268 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001269 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001270 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001271 return;
1272 }
1273
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001274 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001275 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1276
1277 if (!autoRebootAttemptsLeftPtr)
1278 {
1279 messages::internalError(aResp->res);
1280 return;
1281 }
1282
1283 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1284 << *autoRebootAttemptsLeftPtr;
1285
1286 aResp->res
1287 .jsonValue["Boot"]
1288 ["RemainingAutomaticRetryAttempts"] =
1289 *autoRebootAttemptsLeftPtr;
1290 },
1291 "xyz.openbmc_project.State.Host",
1292 "/xyz/openbmc_project/state/host0",
1293 "org.freedesktop.DBus.Properties", "Get",
1294 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1295 "AttemptsLeft");
1296 }
1297 else
1298 {
1299 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1300 "Disabled";
1301 }
1302
1303 // Not on D-Bus. Hardcoded here:
1304 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1305 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001306
1307 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1308 // and RetryAttempts. OpenBMC only supports Disabled and
1309 // RetryAttempts.
1310 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1311 "AllowableValues"] = {"Disabled",
1312 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001313 },
1314 "xyz.openbmc_project.Settings",
1315 "/xyz/openbmc_project/control/host0/auto_reboot",
1316 "org.freedesktop.DBus.Properties", "Get",
1317 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1318}
1319
1320/**
George Liuc6a620f2020-04-10 17:18:11 +08001321 * @brief Retrieves power restore policy over DBUS.
1322 *
1323 * @param[in] aResp Shared pointer for generating response message.
1324 *
1325 * @return None.
1326 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001327inline void
1328 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001329{
1330 BMCWEB_LOG_DEBUG << "Get power restore policy";
1331
1332 crow::connections::systemBus->async_method_call(
1333 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001334 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001335 if (ec)
1336 {
1337 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1338 return;
1339 }
1340
1341 const boost::container::flat_map<std::string, std::string>
1342 policyMaps = {
1343 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1344 "AlwaysOn",
1345 "AlwaysOn"},
1346 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1347 "AlwaysOff",
1348 "AlwaysOff"},
1349 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001350 "Restore",
George Liuc6a620f2020-04-10 17:18:11 +08001351 "LastState"}};
1352
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001353 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001354
1355 if (!policyPtr)
1356 {
1357 messages::internalError(aResp->res);
1358 return;
1359 }
1360
1361 auto policyMapsIt = policyMaps.find(*policyPtr);
1362 if (policyMapsIt == policyMaps.end())
1363 {
1364 messages::internalError(aResp->res);
1365 return;
1366 }
1367
1368 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1369 },
1370 "xyz.openbmc_project.Settings",
1371 "/xyz/openbmc_project/control/host0/power_restore_policy",
1372 "org.freedesktop.DBus.Properties", "Get",
1373 "xyz.openbmc_project.Control.Power.RestorePolicy",
1374 "PowerRestorePolicy");
1375}
1376
1377/**
Ali Ahmed19817712021-06-29 17:01:52 -05001378 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1379 * TPM is required for booting the host.
1380 *
1381 * @param[in] aResp Shared pointer for generating response message.
1382 *
1383 * @return None.
1384 */
1385inline void getTrustedModuleRequiredToBoot(
1386 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1387{
1388 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1389
1390 crow::connections::systemBus->async_method_call(
1391 [aResp](
1392 const boost::system::error_code ec,
1393 std::vector<std::pair<
1394 std::string,
1395 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1396 subtree) {
1397 if (ec)
1398 {
1399 BMCWEB_LOG_DEBUG
1400 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1401 // This is an optional D-Bus object so just return if
1402 // error occurs
1403 return;
1404 }
1405 if (subtree.size() == 0)
1406 {
1407 // As noted above, this is an optional interface so just return
1408 // if there is no instance found
1409 return;
1410 }
1411
1412 /* When there is more than one TPMEnable object... */
1413 if (subtree.size() > 1)
1414 {
1415 BMCWEB_LOG_DEBUG
1416 << "DBUS response has more than 1 TPM Enable object:"
1417 << subtree.size();
1418 // Throw an internal Error and return
1419 messages::internalError(aResp->res);
1420 return;
1421 }
1422
1423 // Make sure the Dbus response map has a service and objectPath
1424 // field
1425 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1426 {
1427 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1428 messages::internalError(aResp->res);
1429 return;
1430 }
1431
1432 const std::string& path = subtree[0].first;
1433 const std::string& serv = subtree[0].second.begin()->first;
1434
1435 // Valid TPM Enable object found, now reading the current value
1436 crow::connections::systemBus->async_method_call(
1437 [aResp](const boost::system::error_code ec,
1438 std::variant<bool>& tpmRequired) {
1439 if (ec)
1440 {
1441 BMCWEB_LOG_DEBUG
1442 << "D-BUS response error on TPM.Policy Get" << ec;
1443 messages::internalError(aResp->res);
1444 return;
1445 }
1446
1447 const bool* tpmRequiredVal =
1448 std::get_if<bool>(&tpmRequired);
1449
1450 if (!tpmRequiredVal)
1451 {
1452 messages::internalError(aResp->res);
1453 return;
1454 }
1455
1456 if (*tpmRequiredVal == true)
1457 {
1458 aResp->res
1459 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1460 "Required";
1461 }
1462 else
1463 {
1464 aResp->res
1465 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1466 "Disabled";
1467 }
1468 },
1469 serv, path, "org.freedesktop.DBus.Properties", "Get",
1470 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1471 },
1472 "xyz.openbmc_project.ObjectMapper",
1473 "/xyz/openbmc_project/object_mapper",
1474 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1475 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1476}
1477
1478/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001479 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1480 * TPM is required for booting the host.
1481 *
1482 * @param[in] aResp Shared pointer for generating response message.
1483 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1484 *
1485 * @return None.
1486 */
1487inline void setTrustedModuleRequiredToBoot(
1488 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1489{
1490 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1491
1492 crow::connections::systemBus->async_method_call(
1493 [aResp, tpmRequired](
1494 const boost::system::error_code ec,
1495 std::vector<std::pair<
1496 std::string,
1497 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1498 subtree) {
1499 if (ec)
1500 {
1501 BMCWEB_LOG_DEBUG
1502 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1503 messages::internalError(aResp->res);
1504 return;
1505 }
1506 if (subtree.size() == 0)
1507 {
1508 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1509 "TrustedModuleRequiredToBoot");
1510 return;
1511 }
1512
1513 /* When there is more than one TPMEnable object... */
1514 if (subtree.size() > 1)
1515 {
1516 BMCWEB_LOG_DEBUG
1517 << "DBUS response has more than 1 TPM Enable object:"
1518 << subtree.size();
1519 // Throw an internal Error and return
1520 messages::internalError(aResp->res);
1521 return;
1522 }
1523
1524 // Make sure the Dbus response map has a service and objectPath
1525 // field
1526 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1527 {
1528 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1529 messages::internalError(aResp->res);
1530 return;
1531 }
1532
1533 const std::string& path = subtree[0].first;
1534 const std::string& serv = subtree[0].second.begin()->first;
1535
1536 if (serv.empty())
1537 {
1538 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1539 messages::internalError(aResp->res);
1540 return;
1541 }
1542
1543 // Valid TPM Enable object found, now setting the value
1544 crow::connections::systemBus->async_method_call(
1545 [aResp](const boost::system::error_code ec) {
1546 if (ec)
1547 {
1548 BMCWEB_LOG_DEBUG << "DBUS response error: Set "
1549 "TrustedModuleRequiredToBoot"
1550 << ec;
1551 messages::internalError(aResp->res);
1552 return;
1553 }
1554 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1555 },
1556 serv, path, "org.freedesktop.DBus.Properties", "Set",
1557 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1558 std::variant<bool>(tpmRequired));
1559 },
1560 "xyz.openbmc_project.ObjectMapper",
1561 "/xyz/openbmc_project/object_mapper",
1562 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1563 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1564}
1565
1566/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301567 * @brief Sets boot properties into DBUS object(s).
1568 *
1569 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001570 * @param[in] bootType The boot type to set.
1571 * @return Integer error code.
1572 */
1573inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001574 const std::optional<std::string>& bootType)
1575{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001576 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001577
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001578 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001579 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001580 return;
1581 }
1582
1583 // Source target specified
1584 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1585 // Figure out which DBUS interface and property to use
1586 if (*bootType == "Legacy")
1587 {
1588 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1589 }
1590 else if (*bootType == "UEFI")
1591 {
1592 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1593 }
1594 else
1595 {
1596 BMCWEB_LOG_DEBUG << "Invalid property value for "
1597 "BootSourceOverrideMode: "
1598 << *bootType;
1599 messages::propertyValueNotInList(aResp->res, *bootType,
1600 "BootSourceOverrideMode");
1601 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001602 }
1603
1604 // Act on validated parameters
1605 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1606
1607 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001608 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001609 if (ec)
1610 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001611 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1612 if (ec.value() == boost::asio::error::host_unreachable)
1613 {
1614 messages::resourceNotFound(aResp->res, "Set", "BootType");
1615 return;
1616 }
1617 messages::internalError(aResp->res);
1618 return;
1619 }
1620 BMCWEB_LOG_DEBUG << "Boot type update done.";
1621 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001622 "xyz.openbmc_project.Settings",
1623 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001624 "org.freedesktop.DBus.Properties", "Set",
1625 "xyz.openbmc_project.Control.Boot.Type", "BootType",
1626 std::variant<std::string>(bootTypeStr));
1627}
1628
1629/**
1630 * @brief Sets boot properties into DBUS object(s).
1631 *
1632 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001633 * @param[in] bootType The boot type to set.
1634 * @return Integer error code.
1635 */
1636inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1637 const std::optional<std::string>& bootEnable)
1638{
1639 if (!bootEnable)
1640 {
1641 return;
1642 }
1643 // Source target specified
1644 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1645
1646 bool bootOverrideEnable = false;
1647 bool bootOverridePersistent = false;
1648 // Figure out which DBUS interface and property to use
1649 if (*bootEnable == "Disabled")
1650 {
1651 bootOverrideEnable = false;
1652 }
1653 else if (*bootEnable == "Once")
1654 {
1655 bootOverrideEnable = true;
1656 bootOverridePersistent = false;
1657 }
1658 else if (*bootEnable == "Continuous")
1659 {
1660 bootOverrideEnable = true;
1661 bootOverridePersistent = true;
1662 }
1663 else
1664 {
1665 BMCWEB_LOG_DEBUG << "Invalid property value for "
1666 "BootSourceOverrideEnabled: "
1667 << *bootEnable;
1668 messages::propertyValueNotInList(aResp->res, *bootEnable,
1669 "BootSourceOverrideEnabled");
1670 return;
1671 }
1672
1673 // Act on validated parameters
1674 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1675
1676 crow::connections::systemBus->async_method_call(
1677 [aResp](const boost::system::error_code ec) {
1678 if (ec)
1679 {
1680 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1681 messages::internalError(aResp->res);
1682 return;
1683 }
1684 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1685 },
1686 "xyz.openbmc_project.Settings",
1687 "/xyz/openbmc_project/control/host0/boot",
1688 "org.freedesktop.DBus.Properties", "Set",
1689 "xyz.openbmc_project.Object.Enable", "Enabled",
1690 std::variant<bool>(bootOverrideEnable));
1691
1692 if (!bootOverrideEnable)
1693 {
1694 return;
1695 }
1696
1697 // In case boot override is enabled we need to set correct value for the
1698 // 'one_time' enable DBus interface
1699 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1700 << bootOverridePersistent;
1701
1702 crow::connections::systemBus->async_method_call(
1703 [aResp](const boost::system::error_code ec) {
1704 if (ec)
1705 {
1706 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1707 messages::internalError(aResp->res);
1708 return;
1709 }
1710 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1711 },
1712 "xyz.openbmc_project.Settings",
1713 "/xyz/openbmc_project/control/host0/boot/one_time",
1714 "org.freedesktop.DBus.Properties", "Set",
1715 "xyz.openbmc_project.Object.Enable", "Enabled",
1716 std::variant<bool>(!bootOverridePersistent));
1717}
1718
1719/**
1720 * @brief Sets boot properties into DBUS object(s).
1721 *
1722 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301723 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301724 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001725 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301726 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001727inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001728 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301729{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001730 std::string bootSourceStr;
1731 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001732
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001733 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301734 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001735 return;
1736 }
1737
1738 // Source target specified
1739 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1740 // Figure out which DBUS interface and property to use
1741 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1742 {
1743 BMCWEB_LOG_DEBUG
1744 << "Invalid property value for BootSourceOverrideTarget: "
1745 << *bootSource;
1746 messages::propertyValueNotInList(aResp->res, *bootSource,
1747 "BootSourceTargetOverride");
1748 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001749 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301750
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001751 // Act on validated parameters
1752 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1753 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001754
1755 crow::connections::systemBus->async_method_call(
1756 [aResp](const boost::system::error_code ec) {
1757 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301758 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001759 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1760 messages::internalError(aResp->res);
1761 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301762 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001763 BMCWEB_LOG_DEBUG << "Boot source update done.";
1764 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001765 "xyz.openbmc_project.Settings",
1766 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001767 "org.freedesktop.DBus.Properties", "Set",
1768 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1769 std::variant<std::string>(bootSourceStr));
1770
1771 crow::connections::systemBus->async_method_call(
1772 [aResp](const boost::system::error_code ec) {
1773 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301774 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001775 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1776 messages::internalError(aResp->res);
1777 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301778 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001779 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1780 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001781 "xyz.openbmc_project.Settings",
1782 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001783 "org.freedesktop.DBus.Properties", "Set",
1784 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1785 std::variant<std::string>(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001786}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001787
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001788/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001789 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301790 *
1791 * @param[in] aResp Shared pointer for generating response message.
1792 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001793 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301794 * @param[in] bootEnable The boot override enable from incoming RF request.
1795 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001796 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301797 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001798
1799inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1800 const std::optional<std::string>& bootSource,
1801 const std::optional<std::string>& bootType,
1802 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301803{
1804 BMCWEB_LOG_DEBUG << "Set boot information.";
1805
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001806 setBootModeOrSource(aResp, bootSource);
1807 setBootType(aResp, bootType);
1808 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301809}
1810
George Liuc6a620f2020-04-10 17:18:11 +08001811/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001812 * @brief Sets AssetTag
1813 *
1814 * @param[in] aResp Shared pointer for generating response message.
1815 * @param[in] assetTag "AssetTag" from request.
1816 *
1817 * @return None.
1818 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001819inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001820 const std::string& assetTag)
1821{
1822 crow::connections::systemBus->async_method_call(
1823 [aResp, assetTag](
1824 const boost::system::error_code ec,
1825 const std::vector<std::pair<
1826 std::string,
1827 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1828 subtree) {
1829 if (ec)
1830 {
1831 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1832 messages::internalError(aResp->res);
1833 return;
1834 }
1835 if (subtree.size() == 0)
1836 {
1837 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1838 messages::internalError(aResp->res);
1839 return;
1840 }
1841 // Assume only 1 system D-Bus object
1842 // Throw an error if there is more than 1
1843 if (subtree.size() > 1)
1844 {
1845 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1846 messages::internalError(aResp->res);
1847 return;
1848 }
1849 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1850 {
1851 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1852 messages::internalError(aResp->res);
1853 return;
1854 }
1855
1856 const std::string& path = subtree[0].first;
1857 const std::string& service = subtree[0].second.begin()->first;
1858
1859 if (service.empty())
1860 {
1861 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1862 messages::internalError(aResp->res);
1863 return;
1864 }
1865
1866 crow::connections::systemBus->async_method_call(
1867 [aResp](const boost::system::error_code ec2) {
1868 if (ec2)
1869 {
1870 BMCWEB_LOG_DEBUG
1871 << "D-Bus response error on AssetTag Set " << ec2;
1872 messages::internalError(aResp->res);
1873 return;
1874 }
1875 },
1876 service, path, "org.freedesktop.DBus.Properties", "Set",
1877 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1878 std::variant<std::string>(assetTag));
1879 },
1880 "xyz.openbmc_project.ObjectMapper",
1881 "/xyz/openbmc_project/object_mapper",
1882 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1883 "/xyz/openbmc_project/inventory", int32_t(0),
1884 std::array<const char*, 1>{
1885 "xyz.openbmc_project.Inventory.Item.System"});
1886}
1887
1888/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001889 * @brief Sets automaticRetry (Auto Reboot)
1890 *
1891 * @param[in] aResp Shared pointer for generating response message.
1892 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1893 *
1894 * @return None.
1895 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001896inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001897 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001898{
1899 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1900
1901 // OpenBMC only supports "Disabled" and "RetryAttempts".
1902 bool autoRebootEnabled;
1903
1904 if (automaticRetryConfig == "Disabled")
1905 {
1906 autoRebootEnabled = false;
1907 }
1908 else if (automaticRetryConfig == "RetryAttempts")
1909 {
1910 autoRebootEnabled = true;
1911 }
1912 else
1913 {
1914 BMCWEB_LOG_DEBUG << "Invalid property value for "
1915 "AutomaticRetryConfig: "
1916 << automaticRetryConfig;
1917 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1918 "AutomaticRetryConfig");
1919 return;
1920 }
1921
1922 crow::connections::systemBus->async_method_call(
1923 [aResp](const boost::system::error_code ec) {
1924 if (ec)
1925 {
1926 messages::internalError(aResp->res);
1927 return;
1928 }
1929 },
1930 "xyz.openbmc_project.Settings",
1931 "/xyz/openbmc_project/control/host0/auto_reboot",
1932 "org.freedesktop.DBus.Properties", "Set",
1933 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1934 std::variant<bool>(autoRebootEnabled));
1935}
1936
1937/**
George Liuc6a620f2020-04-10 17:18:11 +08001938 * @brief Sets power restore policy properties.
1939 *
1940 * @param[in] aResp Shared pointer for generating response message.
1941 * @param[in] policy power restore policy properties from request.
1942 *
1943 * @return None.
1944 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001945inline void
1946 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1947 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001948{
1949 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1950
1951 const boost::container::flat_map<std::string, std::string> policyMaps = {
1952 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1953 "AlwaysOn"},
1954 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1955 "AlwaysOff"},
1956 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001957 "Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001958
1959 std::string powerRestorPolicy;
1960
Gunnar Mills4e69c902021-01-05 19:50:11 -06001961 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001962 if (policyMapsIt == policyMaps.end())
1963 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001964 messages::propertyValueNotInList(aResp->res, policy,
1965 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001966 return;
1967 }
1968
1969 powerRestorPolicy = policyMapsIt->second;
1970
1971 crow::connections::systemBus->async_method_call(
1972 [aResp](const boost::system::error_code ec) {
1973 if (ec)
1974 {
1975 messages::internalError(aResp->res);
1976 return;
1977 }
1978 },
1979 "xyz.openbmc_project.Settings",
1980 "/xyz/openbmc_project/control/host0/power_restore_policy",
1981 "org.freedesktop.DBus.Properties", "Set",
1982 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1983 std::variant<std::string>(powerRestorPolicy));
1984}
1985
AppaRao Pulia6349912019-10-18 17:16:08 +05301986#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1987/**
1988 * @brief Retrieves provisioning status
1989 *
1990 * @param[in] aResp Shared pointer for completing asynchronous calls.
1991 *
1992 * @return None.
1993 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001994inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301995{
1996 BMCWEB_LOG_DEBUG << "Get OEM information.";
1997 crow::connections::systemBus->async_method_call(
1998 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001999 const std::vector<std::pair<std::string, VariantType>>&
2000 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05302001 nlohmann::json& oemPFR =
2002 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07002003 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
2004 "#OemComputerSystem.OpenBmc";
2005 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
2006
AppaRao Pulia6349912019-10-18 17:16:08 +05302007 if (ec)
2008 {
2009 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05302010 // not an error, don't have to have the interface
2011 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05302012 return;
2013 }
2014
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002015 const bool* provState = nullptr;
2016 const bool* lockState = nullptr;
2017 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05302018 propertiesList)
2019 {
2020 if (property.first == "UfmProvisioned")
2021 {
2022 provState = std::get_if<bool>(&property.second);
2023 }
2024 else if (property.first == "UfmLocked")
2025 {
2026 lockState = std::get_if<bool>(&property.second);
2027 }
2028 }
2029
2030 if ((provState == nullptr) || (lockState == nullptr))
2031 {
2032 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
2033 messages::internalError(aResp->res);
2034 return;
2035 }
2036
AppaRao Pulia6349912019-10-18 17:16:08 +05302037 if (*provState == true)
2038 {
2039 if (*lockState == true)
2040 {
2041 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
2042 }
2043 else
2044 {
2045 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
2046 }
2047 }
2048 else
2049 {
2050 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2051 }
2052 },
2053 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2054 "org.freedesktop.DBus.Properties", "GetAll",
2055 "xyz.openbmc_project.PFR.Attributes");
2056}
2057#endif
2058
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302059/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002060 * @brief Translate the PowerMode to a response message.
2061 *
2062 * @param[in] aResp Shared pointer for generating response message.
2063 * @param[in] modeValue PowerMode value to be translated
2064 *
2065 * @return None.
2066 */
2067inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2068 const std::string& modeValue)
2069{
2070 std::string modeString;
2071
2072 if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2073 "PowerMode.Static")
2074 {
2075 aResp->res.jsonValue["PowerMode"] = "Static";
2076 }
2077 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2078 "PowerMode.MaximumPerformance")
2079 {
2080 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2081 }
2082 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2083 "PowerMode.PowerSaving")
2084 {
2085 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2086 }
2087 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
2088 "PowerMode.OEM")
2089 {
2090 aResp->res.jsonValue["PowerMode"] = "OEM";
2091 }
2092 else
2093 {
2094 // Any other values would be invalid
2095 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2096 messages::internalError(aResp->res);
2097 }
2098}
2099
2100/**
2101 * @brief Retrieves system power mode
2102 *
2103 * @param[in] aResp Shared pointer for generating response message.
2104 *
2105 * @return None.
2106 */
2107inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2108{
2109 BMCWEB_LOG_DEBUG << "Get power mode.";
2110
2111 // Get Power Mode object path:
2112 crow::connections::systemBus->async_method_call(
2113 [aResp](
2114 const boost::system::error_code ec,
2115 const std::vector<std::pair<
2116 std::string,
2117 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2118 subtree) {
2119 if (ec)
2120 {
2121 BMCWEB_LOG_DEBUG
2122 << "DBUS response error on Power.Mode GetSubTree " << ec;
2123 // This is an optional D-Bus object so just return if
2124 // error occurs
2125 return;
2126 }
2127 if (subtree.empty())
2128 {
2129 // As noted above, this is an optional interface so just return
2130 // if there is no instance found
2131 return;
2132 }
2133 if (subtree.size() > 1)
2134 {
2135 // More then one PowerMode object is not supported and is an
2136 // error
2137 BMCWEB_LOG_DEBUG
2138 << "Found more than 1 system D-Bus Power.Mode objects: "
2139 << subtree.size();
2140 messages::internalError(aResp->res);
2141 return;
2142 }
2143 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2144 {
2145 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2146 messages::internalError(aResp->res);
2147 return;
2148 }
2149 const std::string& path = subtree[0].first;
2150 const std::string& service = subtree[0].second.begin()->first;
2151 if (service.empty())
2152 {
2153 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2154 messages::internalError(aResp->res);
2155 return;
2156 }
2157 // Valid Power Mode object found, now read the current value
2158 crow::connections::systemBus->async_method_call(
2159 [aResp](const boost::system::error_code ec,
2160 const std::variant<std::string>& pmode) {
2161 if (ec)
2162 {
2163 BMCWEB_LOG_DEBUG
2164 << "DBUS response error on PowerMode Get: " << ec;
2165 messages::internalError(aResp->res);
2166 return;
2167 }
2168
2169 const std::string* s = std::get_if<std::string>(&pmode);
2170 if (s == nullptr)
2171 {
2172 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
2173 messages::internalError(aResp->res);
2174 return;
2175 }
2176
2177 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2178 {"Static", "MaximumPerformance", "PowerSaving"};
2179
2180 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
2181 translatePowerMode(aResp, *s);
2182 },
2183 service, path, "org.freedesktop.DBus.Properties", "Get",
2184 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
2185 },
2186 "xyz.openbmc_project.ObjectMapper",
2187 "/xyz/openbmc_project/object_mapper",
2188 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2189 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2190}
2191
2192/**
2193 * @brief Validate the specified mode is valid and return the PowerMode
2194 * name associated with that string
2195 *
2196 * @param[in] aResp Shared pointer for generating response message.
2197 * @param[in] modeString String representing the desired PowerMode
2198 *
2199 * @return PowerMode value or empty string if mode is not valid
2200 */
2201inline std::string
2202 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2203 const std::string& modeString)
2204{
2205 std::string mode;
2206
2207 if (modeString == "Static")
2208 {
2209 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2210 }
2211 else if (modeString == "MaximumPerformance")
2212 {
2213 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
2214 "MaximumPerformance";
2215 }
2216 else if (modeString == "PowerSaving")
2217 {
2218 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2219 }
2220 else
2221 {
2222 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2223 }
2224 return mode;
2225}
2226
2227/**
2228 * @brief Sets system power mode.
2229 *
2230 * @param[in] aResp Shared pointer for generating response message.
2231 * @param[in] pmode System power mode from request.
2232 *
2233 * @return None.
2234 */
2235inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2236 const std::string& pmode)
2237{
2238 BMCWEB_LOG_DEBUG << "Set power mode.";
2239
2240 std::string powerMode = validatePowerMode(aResp, pmode);
2241 if (powerMode.empty())
2242 {
2243 return;
2244 }
2245
2246 // Get Power Mode object path:
2247 crow::connections::systemBus->async_method_call(
2248 [aResp, powerMode](
2249 const boost::system::error_code ec,
2250 const std::vector<std::pair<
2251 std::string,
2252 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2253 subtree) {
2254 if (ec)
2255 {
2256 BMCWEB_LOG_DEBUG
2257 << "DBUS response error on Power.Mode GetSubTree " << ec;
2258 // This is an optional D-Bus object, but user attempted to patch
2259 messages::internalError(aResp->res);
2260 return;
2261 }
2262 if (subtree.empty())
2263 {
2264 // This is an optional D-Bus object, but user attempted to patch
2265 messages::resourceNotFound(aResp->res, "ComputerSystem",
2266 "PowerMode");
2267 return;
2268 }
2269 if (subtree.size() > 1)
2270 {
2271 // More then one PowerMode object is not supported and is an
2272 // error
2273 BMCWEB_LOG_DEBUG
2274 << "Found more than 1 system D-Bus Power.Mode objects: "
2275 << subtree.size();
2276 messages::internalError(aResp->res);
2277 return;
2278 }
2279 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2280 {
2281 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2282 messages::internalError(aResp->res);
2283 return;
2284 }
2285 const std::string& path = subtree[0].first;
2286 const std::string& service = subtree[0].second.begin()->first;
2287 if (service.empty())
2288 {
2289 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2290 messages::internalError(aResp->res);
2291 return;
2292 }
2293
2294 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2295 << path;
2296
2297 // Set the Power Mode property
2298 crow::connections::systemBus->async_method_call(
2299 [aResp](const boost::system::error_code ec) {
2300 if (ec)
2301 {
2302 messages::internalError(aResp->res);
2303 return;
2304 }
2305 },
2306 service, path, "org.freedesktop.DBus.Properties", "Set",
2307 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2308 std::variant<std::string>(powerMode));
2309 },
2310 "xyz.openbmc_project.ObjectMapper",
2311 "/xyz/openbmc_project/object_mapper",
2312 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2313 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2314}
2315
2316/**
Yong Li51709ff2019-09-30 14:13:04 +08002317 * @brief Translates watchdog timeout action DBUS property value to redfish.
2318 *
2319 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2320 *
2321 * @return Returns as a string, the timeout action in Redfish terms. If
2322 * translation cannot be done, returns an empty string.
2323 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002324inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002325{
2326 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2327 {
2328 return "None";
2329 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002330 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002331 {
2332 return "ResetSystem";
2333 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002334 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002335 {
2336 return "PowerDown";
2337 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002338 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002339 {
2340 return "PowerCycle";
2341 }
2342
2343 return "";
2344}
2345
2346/**
Yong Lic45f0082019-10-10 14:19:01 +08002347 *@brief Translates timeout action from Redfish to DBUS property value.
2348 *
2349 *@param[in] rfAction The timeout action in Redfish.
2350 *
2351 *@return Returns as a string, the time_out action as expected by DBUS.
2352 *If translation cannot be done, returns an empty string.
2353 */
2354
Ed Tanous23a21a12020-07-25 04:45:05 +00002355inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002356{
2357 if (rfAction == "None")
2358 {
2359 return "xyz.openbmc_project.State.Watchdog.Action.None";
2360 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002361 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002362 {
2363 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2364 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002365 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002366 {
2367 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2368 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002369 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002370 {
2371 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2372 }
2373
2374 return "";
2375}
2376
2377/**
Yong Li51709ff2019-09-30 14:13:04 +08002378 * @brief Retrieves host watchdog timer properties over DBUS
2379 *
2380 * @param[in] aResp Shared pointer for completing asynchronous calls.
2381 *
2382 * @return None.
2383 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002384inline void
2385 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002386{
2387 BMCWEB_LOG_DEBUG << "Get host watchodg";
2388 crow::connections::systemBus->async_method_call(
2389 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002390 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002391 if (ec)
2392 {
2393 // watchdog service is stopped
2394 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2395 return;
2396 }
2397
2398 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2399
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002400 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002401 aResp->res.jsonValue["HostWatchdogTimer"];
2402
2403 // watchdog service is running/enabled
2404 hostWatchdogTimer["Status"]["State"] = "Enabled";
2405
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002406 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002407 {
2408 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2409 if (property.first == "Enabled")
2410 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002411 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002412
2413 if (!state)
2414 {
2415 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002416 return;
Yong Li51709ff2019-09-30 14:13:04 +08002417 }
2418
2419 hostWatchdogTimer["FunctionEnabled"] = *state;
2420 }
2421 else if (property.first == "ExpireAction")
2422 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002423 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002424 std::get_if<std::string>(&property.second);
2425 if (!s)
2426 {
2427 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002428 return;
Yong Li51709ff2019-09-30 14:13:04 +08002429 }
2430
2431 std::string action = dbusToRfWatchdogAction(*s);
2432 if (action.empty())
2433 {
2434 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002435 return;
Yong Li51709ff2019-09-30 14:13:04 +08002436 }
2437 hostWatchdogTimer["TimeoutAction"] = action;
2438 }
2439 }
2440 },
2441 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2442 "org.freedesktop.DBus.Properties", "GetAll",
2443 "xyz.openbmc_project.State.Watchdog");
2444}
2445
2446/**
Yong Lic45f0082019-10-10 14:19:01 +08002447 * @brief Sets Host WatchDog Timer properties.
2448 *
2449 * @param[in] aResp Shared pointer for generating response message.
2450 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2451 * RF request.
2452 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2453 *
2454 * @return None.
2455 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002456inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002457 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002458 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002459{
2460 BMCWEB_LOG_DEBUG << "Set host watchdog";
2461
2462 if (wdtTimeOutAction)
2463 {
2464 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2465 // check if TimeOut Action is Valid
2466 if (wdtTimeOutActStr.empty())
2467 {
2468 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2469 << *wdtTimeOutAction;
2470 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2471 "TimeoutAction");
2472 return;
2473 }
2474
2475 crow::connections::systemBus->async_method_call(
2476 [aResp](const boost::system::error_code ec) {
2477 if (ec)
2478 {
2479 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2480 messages::internalError(aResp->res);
2481 return;
2482 }
2483 },
2484 "xyz.openbmc_project.Watchdog",
2485 "/xyz/openbmc_project/watchdog/host0",
2486 "org.freedesktop.DBus.Properties", "Set",
2487 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2488 std::variant<std::string>(wdtTimeOutActStr));
2489 }
2490
2491 if (wdtEnable)
2492 {
2493 crow::connections::systemBus->async_method_call(
2494 [aResp](const boost::system::error_code ec) {
2495 if (ec)
2496 {
2497 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2498 messages::internalError(aResp->res);
2499 return;
2500 }
2501 },
2502 "xyz.openbmc_project.Watchdog",
2503 "/xyz/openbmc_project/watchdog/host0",
2504 "org.freedesktop.DBus.Properties", "Set",
2505 "xyz.openbmc_project.State.Watchdog", "Enabled",
2506 std::variant<bool>(*wdtEnable));
2507 }
2508}
2509
2510/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002511 * SystemsCollection derived class for delivering ComputerSystems Collection
2512 * Schema
2513 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002514inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002515{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002516 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002517 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002518 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002519 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002520 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2521 asyncResp->res.jsonValue["@odata.type"] =
2522 "#ComputerSystemCollection.ComputerSystemCollection";
2523 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2524 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002525
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002526 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002527 [asyncResp](const boost::system::error_code ec,
2528 const std::variant<std::string>& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002529 nlohmann::json& ifaceArray =
2530 asyncResp->res.jsonValue["Members"];
2531 ifaceArray = nlohmann::json::array();
2532 auto& count =
2533 asyncResp->res.jsonValue["Members@odata.count"];
2534 ifaceArray.push_back(
2535 {{"@odata.id", "/redfish/v1/Systems/system"}});
2536 count = ifaceArray.size();
2537 if (!ec)
2538 {
2539 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2540 ifaceArray.push_back(
2541 {{"@odata.id",
2542 "/redfish/v1/Systems/hypervisor"}});
2543 count = ifaceArray.size();
2544 }
2545 },
2546 "xyz.openbmc_project.Settings",
2547 "/xyz/openbmc_project/network/hypervisor",
2548 "org.freedesktop.DBus.Properties", "Get",
2549 "xyz.openbmc_project.Network.SystemConfiguration",
2550 "HostName");
2551 });
2552}
Sunitha Harish462023a2020-02-19 08:34:59 -06002553
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002554/**
2555 * Function transceives data with dbus directly.
2556 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002557inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002558{
2559 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2560 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2561 constexpr char const* interfaceName =
2562 "xyz.openbmc_project.Control.Host.NMI";
2563 constexpr char const* method = "NMI";
2564
2565 crow::connections::systemBus->async_method_call(
2566 [asyncResp](const boost::system::error_code ec) {
2567 if (ec)
2568 {
2569 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2570 messages::internalError(asyncResp->res);
2571 return;
2572 }
2573 messages::success(asyncResp->res);
2574 },
2575 serviceName, objectPath, interfaceName, method);
2576}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002577
2578/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002579 * SystemActionsReset class supports handle POST method for Reset action.
2580 * The class retrieves and sends data directly to D-Bus.
2581 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002582inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002583{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002584 /**
2585 * Function handles POST method request.
2586 * Analyzes POST body message before sends Reset request data to D-Bus.
2587 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002588 BMCWEB_ROUTE(app,
2589 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002590 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002591 .methods(
2592 boost::beast::http::verb::
2593 post)([](const crow::Request& req,
2594 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2595 std::string resetType;
2596 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2597 resetType))
2598 {
2599 return;
2600 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002601
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002602 // Get the command and host vs. chassis
2603 std::string command;
2604 bool hostCommand;
2605 if ((resetType == "On") || (resetType == "ForceOn"))
2606 {
2607 command = "xyz.openbmc_project.State.Host.Transition.On";
2608 hostCommand = true;
2609 }
2610 else if (resetType == "ForceOff")
2611 {
2612 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2613 hostCommand = false;
2614 }
2615 else if (resetType == "ForceRestart")
2616 {
2617 command =
2618 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2619 hostCommand = true;
2620 }
2621 else if (resetType == "GracefulShutdown")
2622 {
2623 command = "xyz.openbmc_project.State.Host.Transition.Off";
2624 hostCommand = true;
2625 }
2626 else if (resetType == "GracefulRestart")
2627 {
2628 command = "xyz.openbmc_project.State.Host.Transition."
2629 "GracefulWarmReboot";
2630 hostCommand = true;
2631 }
2632 else if (resetType == "PowerCycle")
2633 {
2634 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2635 hostCommand = true;
2636 }
2637 else if (resetType == "Nmi")
2638 {
2639 doNMI(asyncResp);
2640 return;
2641 }
2642 else
2643 {
2644 messages::actionParameterUnknown(asyncResp->res, "Reset",
2645 resetType);
2646 return;
2647 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002648
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002649 if (hostCommand)
2650 {
2651 crow::connections::systemBus->async_method_call(
2652 [asyncResp, resetType](const boost::system::error_code ec) {
2653 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002654 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002655 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2656 if (ec.value() ==
2657 boost::asio::error::invalid_argument)
2658 {
2659 messages::actionParameterNotSupported(
2660 asyncResp->res, resetType, "Reset");
2661 }
2662 else
2663 {
2664 messages::internalError(asyncResp->res);
2665 }
2666 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002667 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002668 messages::success(asyncResp->res);
2669 },
2670 "xyz.openbmc_project.State.Host",
2671 "/xyz/openbmc_project/state/host0",
2672 "org.freedesktop.DBus.Properties", "Set",
2673 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2674 std::variant<std::string>{command});
2675 }
2676 else
2677 {
2678 crow::connections::systemBus->async_method_call(
2679 [asyncResp, resetType](const boost::system::error_code ec) {
2680 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002681 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002682 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2683 if (ec.value() ==
2684 boost::asio::error::invalid_argument)
2685 {
2686 messages::actionParameterNotSupported(
2687 asyncResp->res, resetType, "Reset");
2688 }
2689 else
2690 {
2691 messages::internalError(asyncResp->res);
2692 }
2693 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002694 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002695 messages::success(asyncResp->res);
2696 },
2697 "xyz.openbmc_project.State.Chassis",
2698 "/xyz/openbmc_project/state/chassis0",
2699 "org.freedesktop.DBus.Properties", "Set",
2700 "xyz.openbmc_project.State.Chassis",
2701 "RequestedPowerTransition",
2702 std::variant<std::string>{command});
2703 }
2704 });
2705}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002706
2707/**
Ed Tanous66173382018-08-15 18:20:59 -07002708 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002709 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002710inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002711{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002712
Ed Tanous1abe55e2018-09-05 08:30:59 -07002713 /**
2714 * Functions triggers appropriate requests on DBus
2715 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002716 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002717 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002718 .methods(
2719 boost::beast::http::verb::
2720 get)([](const crow::Request&,
2721 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2722 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain3a2d04242021-05-28 16:57:10 -05002723 "#ComputerSystem.v1_15_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002724 asyncResp->res.jsonValue["Name"] = "system";
2725 asyncResp->res.jsonValue["Id"] = "system";
2726 asyncResp->res.jsonValue["SystemType"] = "Physical";
2727 asyncResp->res.jsonValue["Description"] = "Computer System";
2728 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2729 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2730 "Disabled";
2731 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2732 uint64_t(0);
2733 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2734 "Disabled";
2735 asyncResp->res.jsonValue["@odata.id"] =
2736 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002737
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002738 asyncResp->res.jsonValue["Processors"] = {
2739 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2740 asyncResp->res.jsonValue["Memory"] = {
2741 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2742 asyncResp->res.jsonValue["Storage"] = {
2743 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002744
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002745 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2746 {"target",
2747 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2748 {"@Redfish.ActionInfo",
2749 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002750
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002751 asyncResp->res.jsonValue["LogServices"] = {
2752 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002753
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002754 asyncResp->res.jsonValue["Bios"] = {
2755 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002756
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002757 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2758 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002759
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002760 asyncResp->res.jsonValue["Status"] = {
2761 {"Health", "OK"},
2762 {"State", "Enabled"},
2763 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002764
2765 // Fill in SerialConsole info
2766 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2767 15;
2768 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2769 {"ServiceEnabled", true},
2770 };
2771 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2772 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2773 {"ServiceEnabled", true},
2774 {"Port", 2200},
2775 // https://github.com/openbmc/docs/blob/master/console.md
2776 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2777 };
2778
2779#ifdef BMCWEB_ENABLE_KVM
2780 // Fill in GraphicalConsole info
2781 asyncResp->res.jsonValue["GraphicalConsole"] = {
2782 {"ServiceEnabled", true},
2783 {"MaxConcurrentSessions", 4},
2784 {"ConnectTypesSupported", {"KVMIP"}},
2785 };
2786#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002787 constexpr const std::array<const char*, 4> inventoryForSystems = {
2788 "xyz.openbmc_project.Inventory.Item.Dimm",
2789 "xyz.openbmc_project.Inventory.Item.Cpu",
2790 "xyz.openbmc_project.Inventory.Item.Drive",
2791 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002792
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002793 auto health = std::make_shared<HealthPopulate>(asyncResp);
2794 crow::connections::systemBus->async_method_call(
2795 [health](const boost::system::error_code ec,
2796 std::vector<std::string>& resp) {
2797 if (ec)
2798 {
2799 // no inventory
2800 return;
2801 }
2802
2803 health->inventory = std::move(resp);
2804 },
2805 "xyz.openbmc_project.ObjectMapper",
2806 "/xyz/openbmc_project/object_mapper",
2807 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2808 int32_t(0), inventoryForSystems);
2809
2810 health->populate();
2811
2812 getMainChassisId(
2813 asyncResp, [](const std::string& chassisId,
2814 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2815 aRsp->res.jsonValue["Links"]["Chassis"] = {
2816 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2817 });
2818
2819 getLocationIndicatorActive(asyncResp);
2820 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2821 getIndicatorLedState(asyncResp);
2822 getComputerSystem(asyncResp, health);
2823 getHostState(asyncResp);
2824 getBootProperties(asyncResp);
2825 getBootProgress(asyncResp);
2826 getPCIeDeviceList(asyncResp, "PCIeDevices");
2827 getHostWatchdogTimer(asyncResp);
2828 getPowerRestorePolicy(asyncResp);
2829 getAutomaticRetry(asyncResp);
2830 getLastResetTime(asyncResp);
2831#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2832 getProvisioningStatus(asyncResp);
2833#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002834 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002835 getPowerMode(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002836 });
2837 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002838 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839 .methods(boost::beast::http::verb::patch)(
2840 [](const crow::Request& req,
2841 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2842 std::optional<bool> locationIndicatorActive;
2843 std::optional<std::string> indicatorLed;
2844 std::optional<nlohmann::json> bootProps;
2845 std::optional<nlohmann::json> wdtTimerProps;
2846 std::optional<std::string> assetTag;
2847 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002848 std::optional<std::string> powerMode;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05002849 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002850 if (!json_util::readJson(
2851 req, asyncResp->res, "IndicatorLED", indicatorLed,
2852 "LocationIndicatorActive", locationIndicatorActive,
2853 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2854 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Ali Ahmed1c05dae2021-06-29 17:49:22 -05002855 assetTag, "PowerMode", powerMode,
2856 "TrustedModuleRequiredToBoot",
2857 trustedModuleRequiredToBoot))
James Feistb49ac872019-05-21 15:12:01 -07002858 {
James Feistb49ac872019-05-21 15:12:01 -07002859 return;
2860 }
2861
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002862 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07002863
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002864 if (assetTag)
2865 {
2866 setAssetTag(asyncResp, *assetTag);
2867 }
James Feistb49ac872019-05-21 15:12:01 -07002868
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002869 if (wdtTimerProps)
2870 {
2871 std::optional<bool> wdtEnable;
2872 std::optional<std::string> wdtTimeOutAction;
2873
2874 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
2875 "FunctionEnabled", wdtEnable,
2876 "TimeoutAction", wdtTimeOutAction))
2877 {
2878 return;
2879 }
2880 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
2881 }
2882
2883 if (bootProps)
2884 {
2885 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002886 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002887 std::optional<std::string> bootEnable;
2888 std::optional<std::string> automaticRetryConfig;
2889
2890 if (!json_util::readJson(
2891 *bootProps, asyncResp->res,
2892 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002893 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002894 "BootSourceOverrideEnabled", bootEnable,
2895 "AutomaticRetryConfig", automaticRetryConfig))
2896 {
2897 return;
2898 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03002899
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03002900 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002901 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03002902 setBootProperties(asyncResp, bootSource, bootType,
2903 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002904 }
2905 if (automaticRetryConfig)
2906 {
2907 setAutomaticRetry(asyncResp, *automaticRetryConfig);
2908 }
2909 }
2910
2911 if (locationIndicatorActive)
2912 {
2913 setLocationIndicatorActive(asyncResp,
2914 *locationIndicatorActive);
2915 }
2916
2917 // TODO (Gunnar): Remove IndicatorLED after enough time has
2918 // passed
2919 if (indicatorLed)
2920 {
2921 setIndicatorLedState(asyncResp, *indicatorLed);
2922 asyncResp->res.addHeader(
2923 boost::beast::http::field::warning,
2924 "299 - \"IndicatorLED is deprecated. Use "
2925 "LocationIndicatorActive instead.\"");
2926 }
2927
2928 if (powerRestorePolicy)
2929 {
2930 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
2931 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002932
2933 if (powerMode)
2934 {
2935 setPowerMode(asyncResp, *powerMode);
2936 }
Ali Ahmed1c05dae2021-06-29 17:49:22 -05002937
2938 if (trustedModuleRequiredToBoot)
2939 {
2940 setTrustedModuleRequiredToBoot(
2941 asyncResp, *trustedModuleRequiredToBoot);
2942 }
zhanghch058d1b46d2021-04-01 11:18:24 +08002943 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002944}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302945
2946/**
2947 * SystemResetActionInfo derived class for delivering Computer Systems
2948 * ResetType AllowableValues using ResetInfo schema.
2949 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002950inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302951{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302952
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302953 /**
2954 * Functions triggers appropriate requests on DBus
2955 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002956 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07002957 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002958 .methods(boost::beast::http::verb::get)(
2959 [](const crow::Request&,
2960 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2961 asyncResp->res.jsonValue = {
2962 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
2963 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
2964 {"Name", "Reset Action Info"},
2965 {"Id", "ResetActionInfo"},
2966 {"Parameters",
2967 {{{"Name", "ResetType"},
2968 {"Required", true},
2969 {"DataType", "String"},
2970 {"AllowableValues",
2971 {"On", "ForceOff", "ForceOn", "ForceRestart",
2972 "GracefulRestart", "GracefulShutdown", "PowerCycle",
2973 "Nmi"}}}}}};
2974 });
2975}
Ed Tanous1abe55e2018-09-05 08:30:59 -07002976} // namespace redfish