blob: 45a3249091902bdde537146d8200ad80299a7c48 [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/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500714 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530715 *
716 * @param[in] dbusMode The boot mode in DBUS speak.
717 *
718 * @return Returns as a string, the boot mode in Redfish terms. If translation
719 * cannot be done, returns an empty string.
720 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000721inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530722{
723 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
724 {
725 return "None";
726 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700727 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530728 {
729 return "Diags";
730 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700731 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530732 {
733 return "BiosSetup";
734 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700735 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530736}
737
738/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500739 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530740 *
741 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700742 * @param[out] bootSource The DBus source
743 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530744 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700745 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530746 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800747inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500748 const std::string& rfSource,
749 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530750{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700751 // The caller has initialized the bootSource and bootMode to:
752 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
753 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
754 // Only modify the bootSource/bootMode variable needed to achieve the
755 // desired boot action.
756
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530757 if (rfSource == "None")
758 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700759 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530760 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700761 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530762 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700763 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
764 }
765 else if (rfSource == "Hdd")
766 {
767 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
768 }
769 else if (rfSource == "Diags")
770 {
771 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
772 }
773 else if (rfSource == "Cd")
774 {
775 bootSource =
776 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
777 }
778 else if (rfSource == "BiosSetup")
779 {
780 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700782 else if (rfSource == "Usb")
783 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700784 bootSource =
785 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700786 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 else
788 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700789 BMCWEB_LOG_DEBUG << "Invalid property value for "
790 "BootSourceOverrideTarget: "
791 << bootSource;
792 messages::propertyValueNotInList(aResp->res, rfSource,
793 "BootSourceTargetOverride");
794 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530795 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700796 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530797}
Ali Ahmed19817712021-06-29 17:01:52 -0500798
Andrew Geissler978b8802020-11-19 13:36:40 -0600799/**
800 * @brief Retrieves boot progress of the system
801 *
802 * @param[in] aResp Shared pointer for generating response message.
803 *
804 * @return None.
805 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800806inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600807{
808 crow::connections::systemBus->async_method_call(
809 [aResp](const boost::system::error_code ec,
810 const std::variant<std::string>& bootProgress) {
811 if (ec)
812 {
813 // BootProgress is an optional object so just do nothing if
814 // not found
815 return;
816 }
817
818 const std::string* bootProgressStr =
819 std::get_if<std::string>(&bootProgress);
820
821 if (!bootProgressStr)
822 {
823 // Interface implemented but property not found, return error
824 // for that
825 messages::internalError(aResp->res);
826 return;
827 }
828
829 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
830
831 // Now convert the D-Bus BootProgress to the appropriate Redfish
832 // enum
833 std::string rfBpLastState = "None";
834 if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
835 "ProgressStages.Unspecified")
836 {
837 rfBpLastState = "None";
838 }
839 else if (*bootProgressStr ==
840 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
841 "PrimaryProcInit")
842 {
843 rfBpLastState = "PrimaryProcessorInitializationStarted";
844 }
845 else if (*bootProgressStr ==
846 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
847 "BusInit")
848 {
849 rfBpLastState = "BusInitializationStarted";
850 }
851 else if (*bootProgressStr ==
852 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
853 "MemoryInit")
854 {
855 rfBpLastState = "MemoryInitializationStarted";
856 }
857 else if (*bootProgressStr ==
858 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
859 "SecondaryProcInit")
860 {
861 rfBpLastState = "SecondaryProcessorInitializationStarted";
862 }
863 else if (*bootProgressStr ==
864 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
865 "PCIInit")
866 {
867 rfBpLastState = "PCIResourceConfigStarted";
868 }
869 else if (*bootProgressStr ==
870 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
871 "SystemInitComplete")
872 {
873 rfBpLastState = "SystemHardwareInitializationComplete";
874 }
875 else if (*bootProgressStr ==
876 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
877 "OSStart")
878 {
879 rfBpLastState = "OSBootStarted";
880 }
881 else if (*bootProgressStr ==
882 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
883 "OSRunning")
884 {
885 rfBpLastState = "OSRunning";
886 }
887 else
888 {
889 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
890 << *bootProgressStr;
891 // Just return the default
892 }
893
894 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
895 },
896 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
897 "org.freedesktop.DBus.Properties", "Get",
898 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
899}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530900
901/**
902 * @brief Retrieves boot mode over DBUS and fills out the response
903 *
904 * @param[in] aResp Shared pointer for generating response message.
905 * @param[in] bootDbusObj The dbus object to query for boot properties.
906 *
907 * @return None.
908 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800909inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700910 const std::string& bootDbusObj)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530911{
912 crow::connections::systemBus->async_method_call(
913 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500914 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 if (ec)
916 {
917 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
918 messages::internalError(aResp->res);
919 return;
920 }
921
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500922 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923 std::get_if<std::string>(&bootMode);
924
925 if (!bootModeStr)
926 {
927 messages::internalError(aResp->res);
928 return;
929 }
930
931 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
932
933 // TODO (Santosh): Do we need to support override mode?
934 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
935 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
936 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700937 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938
939 if (*bootModeStr !=
940 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
941 {
942 auto rfMode = dbusToRfBootMode(*bootModeStr);
943 if (!rfMode.empty())
944 {
945 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
946 rfMode;
947 }
948 }
949
950 // If the BootSourceOverrideTarget is still "None" at the end,
951 // reset the BootSourceOverrideEnabled to indicate that
952 // overrides are disabled
953 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
954 "None")
955 {
956 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
957 "Disabled";
958 }
959 },
960 "xyz.openbmc_project.Settings", bootDbusObj,
961 "org.freedesktop.DBus.Properties", "Get",
962 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
963}
964
965/**
966 * @brief Retrieves boot source over DBUS
967 *
968 * @param[in] aResp Shared pointer for generating response message.
969 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
970 *
971 * @return None.
972 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800973inline void getBootSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -0700974 bool oneTimeEnabled)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530975{
976 std::string bootDbusObj =
977 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
978 : "/xyz/openbmc_project/control/host0/boot";
979
980 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
981 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
982 (oneTimeEnabled) ? "Once" : "Continuous";
983
984 crow::connections::systemBus->async_method_call(
985 [aResp, bootDbusObj](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500986 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530987 if (ec)
988 {
989 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
990 messages::internalError(aResp->res);
991 return;
992 }
993
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500994 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530995 std::get_if<std::string>(&bootSource);
996
997 if (!bootSourceStr)
998 {
999 messages::internalError(aResp->res);
1000 return;
1001 }
1002 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1003
1004 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1005 if (!rfSource.empty())
1006 {
1007 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1008 rfSource;
1009 }
1010 },
1011 "xyz.openbmc_project.Settings", bootDbusObj,
1012 "org.freedesktop.DBus.Properties", "Get",
1013 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Ed Tanousf23b7292020-10-15 09:41:17 -07001014 getBootMode(aResp, bootDbusObj);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301015}
1016
1017/**
1018 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1019 * get boot source and boot mode.
1020 *
1021 * @param[in] aResp Shared pointer for generating response message.
1022 *
1023 * @return None.
1024 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001025inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026{
1027 BMCWEB_LOG_DEBUG << "Get boot information.";
1028
1029 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001030 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001031 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301032 if (ec)
1033 {
1034 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -07001035 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301036 return;
1037 }
1038
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001039 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301040
1041 if (!oneTimePtr)
1042 {
1043 messages::internalError(aResp->res);
1044 return;
1045 }
1046 getBootSource(aResp, *oneTimePtr);
1047 },
1048 "xyz.openbmc_project.Settings",
1049 "/xyz/openbmc_project/control/host0/boot/one_time",
1050 "org.freedesktop.DBus.Properties", "Get",
1051 "xyz.openbmc_project.Object.Enable", "Enabled");
1052}
1053
1054/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001055 * @brief Retrieves the Last Reset Time
1056 *
1057 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1058 * and power off. Even though this is the "system" Redfish object look at the
1059 * chassis D-Bus interface for the LastStateChangeTime since this has the
1060 * last power operation time.
1061 *
1062 * @param[in] aResp Shared pointer for generating response message.
1063 *
1064 * @return None.
1065 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001066inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001067{
1068 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1069
1070 crow::connections::systemBus->async_method_call(
1071 [aResp](const boost::system::error_code ec,
1072 std::variant<uint64_t>& lastResetTime) {
1073 if (ec)
1074 {
1075 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1076 return;
1077 }
1078
1079 const uint64_t* lastResetTimePtr =
1080 std::get_if<uint64_t>(&lastResetTime);
1081
1082 if (!lastResetTimePtr)
1083 {
1084 messages::internalError(aResp->res);
1085 return;
1086 }
1087 // LastStateChangeTime is epoch time, in milliseconds
1088 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1089 time_t lastResetTimeStamp =
1090 static_cast<time_t>(*lastResetTimePtr / 1000);
1091
1092 // Convert to ISO 8601 standard
1093 aResp->res.jsonValue["LastResetTime"] =
1094 crow::utility::getDateTime(lastResetTimeStamp);
1095 },
1096 "xyz.openbmc_project.State.Chassis",
1097 "/xyz/openbmc_project/state/chassis0",
1098 "org.freedesktop.DBus.Properties", "Get",
1099 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1100}
1101
1102/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001103 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1104 *
1105 * @param[in] aResp Shared pointer for generating response message.
1106 *
1107 * @return None.
1108 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001109inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001110{
1111 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1112
1113 crow::connections::systemBus->async_method_call(
1114 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001115 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001116 if (ec)
1117 {
1118 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1119 return;
1120 }
1121
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001122 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001123 std::get_if<bool>(&autoRebootEnabled);
1124
1125 if (!autoRebootEnabledPtr)
1126 {
1127 messages::internalError(aResp->res);
1128 return;
1129 }
1130
1131 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1132 if (*autoRebootEnabledPtr == true)
1133 {
1134 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1135 "RetryAttempts";
1136 // If AutomaticRetry (AutoReboot) is enabled see how many
1137 // attempts are left
1138 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001139 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001140 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001141 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001142 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001143 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001144 return;
1145 }
1146
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001147 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001148 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1149
1150 if (!autoRebootAttemptsLeftPtr)
1151 {
1152 messages::internalError(aResp->res);
1153 return;
1154 }
1155
1156 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1157 << *autoRebootAttemptsLeftPtr;
1158
1159 aResp->res
1160 .jsonValue["Boot"]
1161 ["RemainingAutomaticRetryAttempts"] =
1162 *autoRebootAttemptsLeftPtr;
1163 },
1164 "xyz.openbmc_project.State.Host",
1165 "/xyz/openbmc_project/state/host0",
1166 "org.freedesktop.DBus.Properties", "Get",
1167 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1168 "AttemptsLeft");
1169 }
1170 else
1171 {
1172 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1173 "Disabled";
1174 }
1175
1176 // Not on D-Bus. Hardcoded here:
1177 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1178 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001179
1180 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1181 // and RetryAttempts. OpenBMC only supports Disabled and
1182 // RetryAttempts.
1183 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1184 "AllowableValues"] = {"Disabled",
1185 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001186 },
1187 "xyz.openbmc_project.Settings",
1188 "/xyz/openbmc_project/control/host0/auto_reboot",
1189 "org.freedesktop.DBus.Properties", "Get",
1190 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1191}
1192
1193/**
George Liuc6a620f2020-04-10 17:18:11 +08001194 * @brief Retrieves power restore policy over DBUS.
1195 *
1196 * @param[in] aResp Shared pointer for generating response message.
1197 *
1198 * @return None.
1199 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001200inline void
1201 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001202{
1203 BMCWEB_LOG_DEBUG << "Get power restore policy";
1204
1205 crow::connections::systemBus->async_method_call(
1206 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001207 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001208 if (ec)
1209 {
1210 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1211 return;
1212 }
1213
1214 const boost::container::flat_map<std::string, std::string>
1215 policyMaps = {
1216 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1217 "AlwaysOn",
1218 "AlwaysOn"},
1219 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1220 "AlwaysOff",
1221 "AlwaysOff"},
1222 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001223 "Restore",
George Liuc6a620f2020-04-10 17:18:11 +08001224 "LastState"}};
1225
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001226 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001227
1228 if (!policyPtr)
1229 {
1230 messages::internalError(aResp->res);
1231 return;
1232 }
1233
1234 auto policyMapsIt = policyMaps.find(*policyPtr);
1235 if (policyMapsIt == policyMaps.end())
1236 {
1237 messages::internalError(aResp->res);
1238 return;
1239 }
1240
1241 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1242 },
1243 "xyz.openbmc_project.Settings",
1244 "/xyz/openbmc_project/control/host0/power_restore_policy",
1245 "org.freedesktop.DBus.Properties", "Get",
1246 "xyz.openbmc_project.Control.Power.RestorePolicy",
1247 "PowerRestorePolicy");
1248}
1249
1250/**
Ali Ahmed19817712021-06-29 17:01:52 -05001251 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1252 * TPM is required for booting the host.
1253 *
1254 * @param[in] aResp Shared pointer for generating response message.
1255 *
1256 * @return None.
1257 */
1258inline void getTrustedModuleRequiredToBoot(
1259 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1260{
1261 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1262
1263 crow::connections::systemBus->async_method_call(
1264 [aResp](
1265 const boost::system::error_code ec,
1266 std::vector<std::pair<
1267 std::string,
1268 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1269 subtree) {
1270 if (ec)
1271 {
1272 BMCWEB_LOG_DEBUG
1273 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1274 // This is an optional D-Bus object so just return if
1275 // error occurs
1276 return;
1277 }
1278 if (subtree.size() == 0)
1279 {
1280 // As noted above, this is an optional interface so just return
1281 // if there is no instance found
1282 return;
1283 }
1284
1285 /* When there is more than one TPMEnable object... */
1286 if (subtree.size() > 1)
1287 {
1288 BMCWEB_LOG_DEBUG
1289 << "DBUS response has more than 1 TPM Enable object:"
1290 << subtree.size();
1291 // Throw an internal Error and return
1292 messages::internalError(aResp->res);
1293 return;
1294 }
1295
1296 // Make sure the Dbus response map has a service and objectPath
1297 // field
1298 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1299 {
1300 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1301 messages::internalError(aResp->res);
1302 return;
1303 }
1304
1305 const std::string& path = subtree[0].first;
1306 const std::string& serv = subtree[0].second.begin()->first;
1307
1308 // Valid TPM Enable object found, now reading the current value
1309 crow::connections::systemBus->async_method_call(
1310 [aResp](const boost::system::error_code ec,
1311 std::variant<bool>& tpmRequired) {
1312 if (ec)
1313 {
1314 BMCWEB_LOG_DEBUG
1315 << "D-BUS response error on TPM.Policy Get" << ec;
1316 messages::internalError(aResp->res);
1317 return;
1318 }
1319
1320 const bool* tpmRequiredVal =
1321 std::get_if<bool>(&tpmRequired);
1322
1323 if (!tpmRequiredVal)
1324 {
1325 messages::internalError(aResp->res);
1326 return;
1327 }
1328
1329 if (*tpmRequiredVal == true)
1330 {
1331 aResp->res
1332 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1333 "Required";
1334 }
1335 else
1336 {
1337 aResp->res
1338 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1339 "Disabled";
1340 }
1341 },
1342 serv, path, "org.freedesktop.DBus.Properties", "Get",
1343 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1344 },
1345 "xyz.openbmc_project.ObjectMapper",
1346 "/xyz/openbmc_project/object_mapper",
1347 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1348 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1349}
1350
1351/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301352 * @brief Sets boot properties into DBUS object(s).
1353 *
1354 * @param[in] aResp Shared pointer for generating response message.
1355 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
1356 * @param[in] bootSource The boot source to set.
1357 * @param[in] bootEnable The source override "enable" to set.
1358 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001359 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301360 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001361inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301362 bool oneTimeEnabled,
Ed Tanousf23b7292020-10-15 09:41:17 -07001363 const std::optional<std::string>& bootSource,
1364 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301365{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001366 std::string bootSourceStr =
1367 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1368 std::string bootModeStr =
1369 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301370 bool oneTimeSetting = oneTimeEnabled;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001371 bool useBootSource = true;
1372
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301373 // Validate incoming parameters
1374 if (bootEnable)
1375 {
1376 if (*bootEnable == "Once")
1377 {
1378 oneTimeSetting = true;
1379 }
1380 else if (*bootEnable == "Continuous")
1381 {
1382 oneTimeSetting = false;
1383 }
1384 else if (*bootEnable == "Disabled")
1385 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001386 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301387 oneTimeSetting = false;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001388 useBootSource = false;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301389 }
1390 else
1391 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301392 BMCWEB_LOG_DEBUG << "Unsupported value for "
1393 "BootSourceOverrideEnabled: "
1394 << *bootEnable;
1395 messages::propertyValueNotInList(aResp->res, *bootEnable,
1396 "BootSourceOverrideEnabled");
1397 return;
1398 }
1399 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301400
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001401 if (bootSource && useBootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301402 {
1403 // Source target specified
1404 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1405 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001406 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1407 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301408 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001409 BMCWEB_LOG_DEBUG
1410 << "Invalid property value for BootSourceOverrideTarget: "
1411 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301412 messages::propertyValueNotInList(aResp->res, *bootSource,
1413 "BootSourceTargetOverride");
1414 return;
1415 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001416 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301417
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001418 // Act on validated parameters
1419 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1420 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001421 const char* bootObj =
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001422 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1423 : "/xyz/openbmc_project/control/host0/boot";
1424
1425 crow::connections::systemBus->async_method_call(
1426 [aResp](const boost::system::error_code ec) {
1427 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301428 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001429 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1430 messages::internalError(aResp->res);
1431 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301432 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001433 BMCWEB_LOG_DEBUG << "Boot source update done.";
1434 },
1435 "xyz.openbmc_project.Settings", bootObj,
1436 "org.freedesktop.DBus.Properties", "Set",
1437 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1438 std::variant<std::string>(bootSourceStr));
1439
1440 crow::connections::systemBus->async_method_call(
1441 [aResp](const boost::system::error_code ec) {
1442 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301443 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001444 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1445 messages::internalError(aResp->res);
1446 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301447 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001448 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1449 },
1450 "xyz.openbmc_project.Settings", bootObj,
1451 "org.freedesktop.DBus.Properties", "Set",
1452 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1453 std::variant<std::string>(bootModeStr));
1454
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301455 crow::connections::systemBus->async_method_call(
1456 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1457 if (ec)
1458 {
1459 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1460 messages::internalError(aResp->res);
1461 return;
1462 }
1463 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1464 },
1465 "xyz.openbmc_project.Settings",
1466 "/xyz/openbmc_project/control/host0/boot/one_time",
1467 "org.freedesktop.DBus.Properties", "Set",
1468 "xyz.openbmc_project.Object.Enable", "Enabled",
1469 std::variant<bool>(oneTimeSetting));
1470}
1471
1472/**
1473 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1474 * set boot source/boot mode properties.
1475 *
1476 * @param[in] aResp Shared pointer for generating response message.
1477 * @param[in] bootSource The boot source from incoming RF request.
1478 * @param[in] bootEnable The boot override enable from incoming RF request.
1479 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001480 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301481 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001482inline void
1483 setBootSourceProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1484 std::optional<std::string> bootSource,
1485 std::optional<std::string> bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301486{
1487 BMCWEB_LOG_DEBUG << "Set boot information.";
1488
1489 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001490 [aResp, bootSource{std::move(bootSource)},
Patrick Williams19bd78d2020-05-13 17:38:24 -05001491 bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001492 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301493 if (ec)
1494 {
1495 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1496 messages::internalError(aResp->res);
1497 return;
1498 }
1499
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001500 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301501
1502 if (!oneTimePtr)
1503 {
1504 messages::internalError(aResp->res);
1505 return;
1506 }
1507
1508 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1509
Ed Tanousf23b7292020-10-15 09:41:17 -07001510 setBootModeOrSource(aResp, *oneTimePtr, bootSource, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301511 },
1512 "xyz.openbmc_project.Settings",
1513 "/xyz/openbmc_project/control/host0/boot/one_time",
1514 "org.freedesktop.DBus.Properties", "Get",
1515 "xyz.openbmc_project.Object.Enable", "Enabled");
1516}
1517
George Liuc6a620f2020-04-10 17:18:11 +08001518/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001519 * @brief Sets AssetTag
1520 *
1521 * @param[in] aResp Shared pointer for generating response message.
1522 * @param[in] assetTag "AssetTag" from request.
1523 *
1524 * @return None.
1525 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001526inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001527 const std::string& assetTag)
1528{
1529 crow::connections::systemBus->async_method_call(
1530 [aResp, assetTag](
1531 const boost::system::error_code ec,
1532 const std::vector<std::pair<
1533 std::string,
1534 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1535 subtree) {
1536 if (ec)
1537 {
1538 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1539 messages::internalError(aResp->res);
1540 return;
1541 }
1542 if (subtree.size() == 0)
1543 {
1544 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1545 messages::internalError(aResp->res);
1546 return;
1547 }
1548 // Assume only 1 system D-Bus object
1549 // Throw an error if there is more than 1
1550 if (subtree.size() > 1)
1551 {
1552 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1553 messages::internalError(aResp->res);
1554 return;
1555 }
1556 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1557 {
1558 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1559 messages::internalError(aResp->res);
1560 return;
1561 }
1562
1563 const std::string& path = subtree[0].first;
1564 const std::string& service = subtree[0].second.begin()->first;
1565
1566 if (service.empty())
1567 {
1568 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1569 messages::internalError(aResp->res);
1570 return;
1571 }
1572
1573 crow::connections::systemBus->async_method_call(
1574 [aResp](const boost::system::error_code ec2) {
1575 if (ec2)
1576 {
1577 BMCWEB_LOG_DEBUG
1578 << "D-Bus response error on AssetTag Set " << ec2;
1579 messages::internalError(aResp->res);
1580 return;
1581 }
1582 },
1583 service, path, "org.freedesktop.DBus.Properties", "Set",
1584 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1585 std::variant<std::string>(assetTag));
1586 },
1587 "xyz.openbmc_project.ObjectMapper",
1588 "/xyz/openbmc_project/object_mapper",
1589 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1590 "/xyz/openbmc_project/inventory", int32_t(0),
1591 std::array<const char*, 1>{
1592 "xyz.openbmc_project.Inventory.Item.System"});
1593}
1594
1595/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001596 * @brief Sets automaticRetry (Auto Reboot)
1597 *
1598 * @param[in] aResp Shared pointer for generating response message.
1599 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1600 *
1601 * @return None.
1602 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001603inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001604 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001605{
1606 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1607
1608 // OpenBMC only supports "Disabled" and "RetryAttempts".
1609 bool autoRebootEnabled;
1610
1611 if (automaticRetryConfig == "Disabled")
1612 {
1613 autoRebootEnabled = false;
1614 }
1615 else if (automaticRetryConfig == "RetryAttempts")
1616 {
1617 autoRebootEnabled = true;
1618 }
1619 else
1620 {
1621 BMCWEB_LOG_DEBUG << "Invalid property value for "
1622 "AutomaticRetryConfig: "
1623 << automaticRetryConfig;
1624 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1625 "AutomaticRetryConfig");
1626 return;
1627 }
1628
1629 crow::connections::systemBus->async_method_call(
1630 [aResp](const boost::system::error_code ec) {
1631 if (ec)
1632 {
1633 messages::internalError(aResp->res);
1634 return;
1635 }
1636 },
1637 "xyz.openbmc_project.Settings",
1638 "/xyz/openbmc_project/control/host0/auto_reboot",
1639 "org.freedesktop.DBus.Properties", "Set",
1640 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1641 std::variant<bool>(autoRebootEnabled));
1642}
1643
1644/**
George Liuc6a620f2020-04-10 17:18:11 +08001645 * @brief Sets power restore policy properties.
1646 *
1647 * @param[in] aResp Shared pointer for generating response message.
1648 * @param[in] policy power restore policy properties from request.
1649 *
1650 * @return None.
1651 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001652inline void
1653 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1654 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001655{
1656 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1657
1658 const boost::container::flat_map<std::string, std::string> policyMaps = {
1659 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1660 "AlwaysOn"},
1661 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1662 "AlwaysOff"},
1663 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001664 "Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001665
1666 std::string powerRestorPolicy;
1667
Gunnar Mills4e69c902021-01-05 19:50:11 -06001668 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001669 if (policyMapsIt == policyMaps.end())
1670 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001671 messages::propertyValueNotInList(aResp->res, policy,
1672 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001673 return;
1674 }
1675
1676 powerRestorPolicy = policyMapsIt->second;
1677
1678 crow::connections::systemBus->async_method_call(
1679 [aResp](const boost::system::error_code ec) {
1680 if (ec)
1681 {
1682 messages::internalError(aResp->res);
1683 return;
1684 }
1685 },
1686 "xyz.openbmc_project.Settings",
1687 "/xyz/openbmc_project/control/host0/power_restore_policy",
1688 "org.freedesktop.DBus.Properties", "Set",
1689 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1690 std::variant<std::string>(powerRestorPolicy));
1691}
1692
AppaRao Pulia6349912019-10-18 17:16:08 +05301693#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1694/**
1695 * @brief Retrieves provisioning status
1696 *
1697 * @param[in] aResp Shared pointer for completing asynchronous calls.
1698 *
1699 * @return None.
1700 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001701inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301702{
1703 BMCWEB_LOG_DEBUG << "Get OEM information.";
1704 crow::connections::systemBus->async_method_call(
1705 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001706 const std::vector<std::pair<std::string, VariantType>>&
1707 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301708 nlohmann::json& oemPFR =
1709 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001710 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1711 "#OemComputerSystem.OpenBmc";
1712 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1713
AppaRao Pulia6349912019-10-18 17:16:08 +05301714 if (ec)
1715 {
1716 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301717 // not an error, don't have to have the interface
1718 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301719 return;
1720 }
1721
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001722 const bool* provState = nullptr;
1723 const bool* lockState = nullptr;
1724 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301725 propertiesList)
1726 {
1727 if (property.first == "UfmProvisioned")
1728 {
1729 provState = std::get_if<bool>(&property.second);
1730 }
1731 else if (property.first == "UfmLocked")
1732 {
1733 lockState = std::get_if<bool>(&property.second);
1734 }
1735 }
1736
1737 if ((provState == nullptr) || (lockState == nullptr))
1738 {
1739 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1740 messages::internalError(aResp->res);
1741 return;
1742 }
1743
AppaRao Pulia6349912019-10-18 17:16:08 +05301744 if (*provState == true)
1745 {
1746 if (*lockState == true)
1747 {
1748 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1749 }
1750 else
1751 {
1752 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1753 }
1754 }
1755 else
1756 {
1757 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1758 }
1759 },
1760 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1761 "org.freedesktop.DBus.Properties", "GetAll",
1762 "xyz.openbmc_project.PFR.Attributes");
1763}
1764#endif
1765
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301766/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001767 * @brief Translate the PowerMode to a response message.
1768 *
1769 * @param[in] aResp Shared pointer for generating response message.
1770 * @param[in] modeValue PowerMode value to be translated
1771 *
1772 * @return None.
1773 */
1774inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1775 const std::string& modeValue)
1776{
1777 std::string modeString;
1778
1779 if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1780 "PowerMode.Static")
1781 {
1782 aResp->res.jsonValue["PowerMode"] = "Static";
1783 }
1784 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1785 "PowerMode.MaximumPerformance")
1786 {
1787 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1788 }
1789 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1790 "PowerMode.PowerSaving")
1791 {
1792 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1793 }
1794 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1795 "PowerMode.OEM")
1796 {
1797 aResp->res.jsonValue["PowerMode"] = "OEM";
1798 }
1799 else
1800 {
1801 // Any other values would be invalid
1802 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1803 messages::internalError(aResp->res);
1804 }
1805}
1806
1807/**
1808 * @brief Retrieves system power mode
1809 *
1810 * @param[in] aResp Shared pointer for generating response message.
1811 *
1812 * @return None.
1813 */
1814inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1815{
1816 BMCWEB_LOG_DEBUG << "Get power mode.";
1817
1818 // Get Power Mode object path:
1819 crow::connections::systemBus->async_method_call(
1820 [aResp](
1821 const boost::system::error_code ec,
1822 const std::vector<std::pair<
1823 std::string,
1824 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1825 subtree) {
1826 if (ec)
1827 {
1828 BMCWEB_LOG_DEBUG
1829 << "DBUS response error on Power.Mode GetSubTree " << ec;
1830 // This is an optional D-Bus object so just return if
1831 // error occurs
1832 return;
1833 }
1834 if (subtree.empty())
1835 {
1836 // As noted above, this is an optional interface so just return
1837 // if there is no instance found
1838 return;
1839 }
1840 if (subtree.size() > 1)
1841 {
1842 // More then one PowerMode object is not supported and is an
1843 // error
1844 BMCWEB_LOG_DEBUG
1845 << "Found more than 1 system D-Bus Power.Mode objects: "
1846 << subtree.size();
1847 messages::internalError(aResp->res);
1848 return;
1849 }
1850 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1851 {
1852 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1853 messages::internalError(aResp->res);
1854 return;
1855 }
1856 const std::string& path = subtree[0].first;
1857 const std::string& service = subtree[0].second.begin()->first;
1858 if (service.empty())
1859 {
1860 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1861 messages::internalError(aResp->res);
1862 return;
1863 }
1864 // Valid Power Mode object found, now read the current value
1865 crow::connections::systemBus->async_method_call(
1866 [aResp](const boost::system::error_code ec,
1867 const std::variant<std::string>& pmode) {
1868 if (ec)
1869 {
1870 BMCWEB_LOG_DEBUG
1871 << "DBUS response error on PowerMode Get: " << ec;
1872 messages::internalError(aResp->res);
1873 return;
1874 }
1875
1876 const std::string* s = std::get_if<std::string>(&pmode);
1877 if (s == nullptr)
1878 {
1879 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
1880 messages::internalError(aResp->res);
1881 return;
1882 }
1883
1884 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1885 {"Static", "MaximumPerformance", "PowerSaving"};
1886
1887 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
1888 translatePowerMode(aResp, *s);
1889 },
1890 service, path, "org.freedesktop.DBus.Properties", "Get",
1891 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
1892 },
1893 "xyz.openbmc_project.ObjectMapper",
1894 "/xyz/openbmc_project/object_mapper",
1895 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1896 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1897}
1898
1899/**
1900 * @brief Validate the specified mode is valid and return the PowerMode
1901 * name associated with that string
1902 *
1903 * @param[in] aResp Shared pointer for generating response message.
1904 * @param[in] modeString String representing the desired PowerMode
1905 *
1906 * @return PowerMode value or empty string if mode is not valid
1907 */
1908inline std::string
1909 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1910 const std::string& modeString)
1911{
1912 std::string mode;
1913
1914 if (modeString == "Static")
1915 {
1916 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
1917 }
1918 else if (modeString == "MaximumPerformance")
1919 {
1920 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
1921 "MaximumPerformance";
1922 }
1923 else if (modeString == "PowerSaving")
1924 {
1925 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
1926 }
1927 else
1928 {
1929 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
1930 }
1931 return mode;
1932}
1933
1934/**
1935 * @brief Sets system power mode.
1936 *
1937 * @param[in] aResp Shared pointer for generating response message.
1938 * @param[in] pmode System power mode from request.
1939 *
1940 * @return None.
1941 */
1942inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1943 const std::string& pmode)
1944{
1945 BMCWEB_LOG_DEBUG << "Set power mode.";
1946
1947 std::string powerMode = validatePowerMode(aResp, pmode);
1948 if (powerMode.empty())
1949 {
1950 return;
1951 }
1952
1953 // Get Power Mode object path:
1954 crow::connections::systemBus->async_method_call(
1955 [aResp, powerMode](
1956 const boost::system::error_code ec,
1957 const std::vector<std::pair<
1958 std::string,
1959 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1960 subtree) {
1961 if (ec)
1962 {
1963 BMCWEB_LOG_DEBUG
1964 << "DBUS response error on Power.Mode GetSubTree " << ec;
1965 // This is an optional D-Bus object, but user attempted to patch
1966 messages::internalError(aResp->res);
1967 return;
1968 }
1969 if (subtree.empty())
1970 {
1971 // This is an optional D-Bus object, but user attempted to patch
1972 messages::resourceNotFound(aResp->res, "ComputerSystem",
1973 "PowerMode");
1974 return;
1975 }
1976 if (subtree.size() > 1)
1977 {
1978 // More then one PowerMode object is not supported and is an
1979 // error
1980 BMCWEB_LOG_DEBUG
1981 << "Found more than 1 system D-Bus Power.Mode objects: "
1982 << subtree.size();
1983 messages::internalError(aResp->res);
1984 return;
1985 }
1986 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1987 {
1988 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1989 messages::internalError(aResp->res);
1990 return;
1991 }
1992 const std::string& path = subtree[0].first;
1993 const std::string& service = subtree[0].second.begin()->first;
1994 if (service.empty())
1995 {
1996 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1997 messages::internalError(aResp->res);
1998 return;
1999 }
2000
2001 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2002 << path;
2003
2004 // Set the Power Mode property
2005 crow::connections::systemBus->async_method_call(
2006 [aResp](const boost::system::error_code ec) {
2007 if (ec)
2008 {
2009 messages::internalError(aResp->res);
2010 return;
2011 }
2012 },
2013 service, path, "org.freedesktop.DBus.Properties", "Set",
2014 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2015 std::variant<std::string>(powerMode));
2016 },
2017 "xyz.openbmc_project.ObjectMapper",
2018 "/xyz/openbmc_project/object_mapper",
2019 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2020 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2021}
2022
2023/**
Yong Li51709ff2019-09-30 14:13:04 +08002024 * @brief Translates watchdog timeout action DBUS property value to redfish.
2025 *
2026 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2027 *
2028 * @return Returns as a string, the timeout action in Redfish terms. If
2029 * translation cannot be done, returns an empty string.
2030 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002031inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002032{
2033 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2034 {
2035 return "None";
2036 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002037 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002038 {
2039 return "ResetSystem";
2040 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002041 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002042 {
2043 return "PowerDown";
2044 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002045 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002046 {
2047 return "PowerCycle";
2048 }
2049
2050 return "";
2051}
2052
2053/**
Yong Lic45f0082019-10-10 14:19:01 +08002054 *@brief Translates timeout action from Redfish to DBUS property value.
2055 *
2056 *@param[in] rfAction The timeout action in Redfish.
2057 *
2058 *@return Returns as a string, the time_out action as expected by DBUS.
2059 *If translation cannot be done, returns an empty string.
2060 */
2061
Ed Tanous23a21a12020-07-25 04:45:05 +00002062inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002063{
2064 if (rfAction == "None")
2065 {
2066 return "xyz.openbmc_project.State.Watchdog.Action.None";
2067 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002068 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002069 {
2070 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2071 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002072 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002073 {
2074 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2075 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002076 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002077 {
2078 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2079 }
2080
2081 return "";
2082}
2083
2084/**
Yong Li51709ff2019-09-30 14:13:04 +08002085 * @brief Retrieves host watchdog timer properties over DBUS
2086 *
2087 * @param[in] aResp Shared pointer for completing asynchronous calls.
2088 *
2089 * @return None.
2090 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002091inline void
2092 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002093{
2094 BMCWEB_LOG_DEBUG << "Get host watchodg";
2095 crow::connections::systemBus->async_method_call(
2096 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002097 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002098 if (ec)
2099 {
2100 // watchdog service is stopped
2101 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2102 return;
2103 }
2104
2105 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2106
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002107 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002108 aResp->res.jsonValue["HostWatchdogTimer"];
2109
2110 // watchdog service is running/enabled
2111 hostWatchdogTimer["Status"]["State"] = "Enabled";
2112
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002113 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002114 {
2115 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2116 if (property.first == "Enabled")
2117 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002118 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002119
2120 if (!state)
2121 {
2122 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002123 return;
Yong Li51709ff2019-09-30 14:13:04 +08002124 }
2125
2126 hostWatchdogTimer["FunctionEnabled"] = *state;
2127 }
2128 else if (property.first == "ExpireAction")
2129 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002130 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002131 std::get_if<std::string>(&property.second);
2132 if (!s)
2133 {
2134 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002135 return;
Yong Li51709ff2019-09-30 14:13:04 +08002136 }
2137
2138 std::string action = dbusToRfWatchdogAction(*s);
2139 if (action.empty())
2140 {
2141 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002142 return;
Yong Li51709ff2019-09-30 14:13:04 +08002143 }
2144 hostWatchdogTimer["TimeoutAction"] = action;
2145 }
2146 }
2147 },
2148 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2149 "org.freedesktop.DBus.Properties", "GetAll",
2150 "xyz.openbmc_project.State.Watchdog");
2151}
2152
2153/**
Yong Lic45f0082019-10-10 14:19:01 +08002154 * @brief Sets Host WatchDog Timer properties.
2155 *
2156 * @param[in] aResp Shared pointer for generating response message.
2157 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2158 * RF request.
2159 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2160 *
2161 * @return None.
2162 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002163inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002164 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002165 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002166{
2167 BMCWEB_LOG_DEBUG << "Set host watchdog";
2168
2169 if (wdtTimeOutAction)
2170 {
2171 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2172 // check if TimeOut Action is Valid
2173 if (wdtTimeOutActStr.empty())
2174 {
2175 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2176 << *wdtTimeOutAction;
2177 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2178 "TimeoutAction");
2179 return;
2180 }
2181
2182 crow::connections::systemBus->async_method_call(
2183 [aResp](const boost::system::error_code ec) {
2184 if (ec)
2185 {
2186 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2187 messages::internalError(aResp->res);
2188 return;
2189 }
2190 },
2191 "xyz.openbmc_project.Watchdog",
2192 "/xyz/openbmc_project/watchdog/host0",
2193 "org.freedesktop.DBus.Properties", "Set",
2194 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2195 std::variant<std::string>(wdtTimeOutActStr));
2196 }
2197
2198 if (wdtEnable)
2199 {
2200 crow::connections::systemBus->async_method_call(
2201 [aResp](const boost::system::error_code ec) {
2202 if (ec)
2203 {
2204 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2205 messages::internalError(aResp->res);
2206 return;
2207 }
2208 },
2209 "xyz.openbmc_project.Watchdog",
2210 "/xyz/openbmc_project/watchdog/host0",
2211 "org.freedesktop.DBus.Properties", "Set",
2212 "xyz.openbmc_project.State.Watchdog", "Enabled",
2213 std::variant<bool>(*wdtEnable));
2214 }
2215}
2216
2217/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002218 * SystemsCollection derived class for delivering ComputerSystems Collection
2219 * Schema
2220 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002221inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002222{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002223 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002224 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002225 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002226 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002227 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2228 asyncResp->res.jsonValue["@odata.type"] =
2229 "#ComputerSystemCollection.ComputerSystemCollection";
2230 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2231 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002232
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002233 crow::connections::systemBus->async_method_call(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002234 [asyncResp](const boost::system::error_code ec,
2235 const std::variant<std::string>& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002236 nlohmann::json& ifaceArray =
2237 asyncResp->res.jsonValue["Members"];
2238 ifaceArray = nlohmann::json::array();
2239 auto& count =
2240 asyncResp->res.jsonValue["Members@odata.count"];
2241 ifaceArray.push_back(
2242 {{"@odata.id", "/redfish/v1/Systems/system"}});
2243 count = ifaceArray.size();
2244 if (!ec)
2245 {
2246 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2247 ifaceArray.push_back(
2248 {{"@odata.id",
2249 "/redfish/v1/Systems/hypervisor"}});
2250 count = ifaceArray.size();
2251 }
2252 },
2253 "xyz.openbmc_project.Settings",
2254 "/xyz/openbmc_project/network/hypervisor",
2255 "org.freedesktop.DBus.Properties", "Get",
2256 "xyz.openbmc_project.Network.SystemConfiguration",
2257 "HostName");
2258 });
2259}
Sunitha Harish462023a2020-02-19 08:34:59 -06002260
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002261/**
2262 * Function transceives data with dbus directly.
2263 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002264inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002265{
2266 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2267 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2268 constexpr char const* interfaceName =
2269 "xyz.openbmc_project.Control.Host.NMI";
2270 constexpr char const* method = "NMI";
2271
2272 crow::connections::systemBus->async_method_call(
2273 [asyncResp](const boost::system::error_code ec) {
2274 if (ec)
2275 {
2276 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2277 messages::internalError(asyncResp->res);
2278 return;
2279 }
2280 messages::success(asyncResp->res);
2281 },
2282 serviceName, objectPath, interfaceName, method);
2283}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002284
2285/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002286 * SystemActionsReset class supports handle POST method for Reset action.
2287 * The class retrieves and sends data directly to D-Bus.
2288 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002289inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002290{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002291 /**
2292 * Function handles POST method request.
2293 * Analyzes POST body message before sends Reset request data to D-Bus.
2294 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002295 BMCWEB_ROUTE(app,
2296 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002297 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002298 .methods(
2299 boost::beast::http::verb::
2300 post)([](const crow::Request& req,
2301 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2302 std::string resetType;
2303 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2304 resetType))
2305 {
2306 return;
2307 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002308
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002309 // Get the command and host vs. chassis
2310 std::string command;
2311 bool hostCommand;
2312 if ((resetType == "On") || (resetType == "ForceOn"))
2313 {
2314 command = "xyz.openbmc_project.State.Host.Transition.On";
2315 hostCommand = true;
2316 }
2317 else if (resetType == "ForceOff")
2318 {
2319 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2320 hostCommand = false;
2321 }
2322 else if (resetType == "ForceRestart")
2323 {
2324 command =
2325 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2326 hostCommand = true;
2327 }
2328 else if (resetType == "GracefulShutdown")
2329 {
2330 command = "xyz.openbmc_project.State.Host.Transition.Off";
2331 hostCommand = true;
2332 }
2333 else if (resetType == "GracefulRestart")
2334 {
2335 command = "xyz.openbmc_project.State.Host.Transition."
2336 "GracefulWarmReboot";
2337 hostCommand = true;
2338 }
2339 else if (resetType == "PowerCycle")
2340 {
2341 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2342 hostCommand = true;
2343 }
2344 else if (resetType == "Nmi")
2345 {
2346 doNMI(asyncResp);
2347 return;
2348 }
2349 else
2350 {
2351 messages::actionParameterUnknown(asyncResp->res, "Reset",
2352 resetType);
2353 return;
2354 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002355
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002356 if (hostCommand)
2357 {
2358 crow::connections::systemBus->async_method_call(
2359 [asyncResp, resetType](const boost::system::error_code ec) {
2360 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002361 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002362 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2363 if (ec.value() ==
2364 boost::asio::error::invalid_argument)
2365 {
2366 messages::actionParameterNotSupported(
2367 asyncResp->res, resetType, "Reset");
2368 }
2369 else
2370 {
2371 messages::internalError(asyncResp->res);
2372 }
2373 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002374 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002375 messages::success(asyncResp->res);
2376 },
2377 "xyz.openbmc_project.State.Host",
2378 "/xyz/openbmc_project/state/host0",
2379 "org.freedesktop.DBus.Properties", "Set",
2380 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2381 std::variant<std::string>{command});
2382 }
2383 else
2384 {
2385 crow::connections::systemBus->async_method_call(
2386 [asyncResp, resetType](const boost::system::error_code ec) {
2387 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002388 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002389 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2390 if (ec.value() ==
2391 boost::asio::error::invalid_argument)
2392 {
2393 messages::actionParameterNotSupported(
2394 asyncResp->res, resetType, "Reset");
2395 }
2396 else
2397 {
2398 messages::internalError(asyncResp->res);
2399 }
2400 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002401 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002402 messages::success(asyncResp->res);
2403 },
2404 "xyz.openbmc_project.State.Chassis",
2405 "/xyz/openbmc_project/state/chassis0",
2406 "org.freedesktop.DBus.Properties", "Set",
2407 "xyz.openbmc_project.State.Chassis",
2408 "RequestedPowerTransition",
2409 std::variant<std::string>{command});
2410 }
2411 });
2412}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002413
2414/**
Ed Tanous66173382018-08-15 18:20:59 -07002415 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002416 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002417inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002418{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002419
Ed Tanous1abe55e2018-09-05 08:30:59 -07002420 /**
2421 * Functions triggers appropriate requests on DBus
2422 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002423 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002424 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002425 .methods(
2426 boost::beast::http::verb::
2427 get)([](const crow::Request&,
2428 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2429 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain3a2d04242021-05-28 16:57:10 -05002430 "#ComputerSystem.v1_15_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002431 asyncResp->res.jsonValue["Name"] = "system";
2432 asyncResp->res.jsonValue["Id"] = "system";
2433 asyncResp->res.jsonValue["SystemType"] = "Physical";
2434 asyncResp->res.jsonValue["Description"] = "Computer System";
2435 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2436 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2437 "Disabled";
2438 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2439 uint64_t(0);
2440 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2441 "Disabled";
2442 asyncResp->res.jsonValue["@odata.id"] =
2443 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002444
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002445 asyncResp->res.jsonValue["Processors"] = {
2446 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2447 asyncResp->res.jsonValue["Memory"] = {
2448 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2449 asyncResp->res.jsonValue["Storage"] = {
2450 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002451
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002452 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2453 {"target",
2454 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2455 {"@Redfish.ActionInfo",
2456 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002457
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002458 asyncResp->res.jsonValue["LogServices"] = {
2459 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002460
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002461 asyncResp->res.jsonValue["Bios"] = {
2462 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002463
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002464 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2465 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002466
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002467 asyncResp->res.jsonValue["Status"] = {
2468 {"Health", "OK"},
2469 {"State", "Enabled"},
2470 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002471
2472 // Fill in SerialConsole info
2473 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2474 15;
2475 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2476 {"ServiceEnabled", true},
2477 };
2478 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2479 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2480 {"ServiceEnabled", true},
2481 {"Port", 2200},
2482 // https://github.com/openbmc/docs/blob/master/console.md
2483 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2484 };
2485
2486#ifdef BMCWEB_ENABLE_KVM
2487 // Fill in GraphicalConsole info
2488 asyncResp->res.jsonValue["GraphicalConsole"] = {
2489 {"ServiceEnabled", true},
2490 {"MaxConcurrentSessions", 4},
2491 {"ConnectTypesSupported", {"KVMIP"}},
2492 };
2493#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002494 constexpr const std::array<const char*, 4> inventoryForSystems = {
2495 "xyz.openbmc_project.Inventory.Item.Dimm",
2496 "xyz.openbmc_project.Inventory.Item.Cpu",
2497 "xyz.openbmc_project.Inventory.Item.Drive",
2498 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002499
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002500 auto health = std::make_shared<HealthPopulate>(asyncResp);
2501 crow::connections::systemBus->async_method_call(
2502 [health](const boost::system::error_code ec,
2503 std::vector<std::string>& resp) {
2504 if (ec)
2505 {
2506 // no inventory
2507 return;
2508 }
2509
2510 health->inventory = std::move(resp);
2511 },
2512 "xyz.openbmc_project.ObjectMapper",
2513 "/xyz/openbmc_project/object_mapper",
2514 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2515 int32_t(0), inventoryForSystems);
2516
2517 health->populate();
2518
2519 getMainChassisId(
2520 asyncResp, [](const std::string& chassisId,
2521 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2522 aRsp->res.jsonValue["Links"]["Chassis"] = {
2523 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2524 });
2525
2526 getLocationIndicatorActive(asyncResp);
2527 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2528 getIndicatorLedState(asyncResp);
2529 getComputerSystem(asyncResp, health);
2530 getHostState(asyncResp);
2531 getBootProperties(asyncResp);
2532 getBootProgress(asyncResp);
2533 getPCIeDeviceList(asyncResp, "PCIeDevices");
2534 getHostWatchdogTimer(asyncResp);
2535 getPowerRestorePolicy(asyncResp);
2536 getAutomaticRetry(asyncResp);
2537 getLastResetTime(asyncResp);
2538#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2539 getProvisioningStatus(asyncResp);
2540#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002541 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002542 getPowerMode(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002543 });
2544 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002545 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002546 .methods(boost::beast::http::verb::patch)(
2547 [](const crow::Request& req,
2548 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2549 std::optional<bool> locationIndicatorActive;
2550 std::optional<std::string> indicatorLed;
2551 std::optional<nlohmann::json> bootProps;
2552 std::optional<nlohmann::json> wdtTimerProps;
2553 std::optional<std::string> assetTag;
2554 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002555 std::optional<std::string> powerMode;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002556
2557 if (!json_util::readJson(
2558 req, asyncResp->res, "IndicatorLED", indicatorLed,
2559 "LocationIndicatorActive", locationIndicatorActive,
2560 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2561 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain3a2d04242021-05-28 16:57:10 -05002562 assetTag, "PowerMode", powerMode))
James Feistb49ac872019-05-21 15:12:01 -07002563 {
James Feistb49ac872019-05-21 15:12:01 -07002564 return;
2565 }
2566
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002567 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07002568
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002569 if (assetTag)
2570 {
2571 setAssetTag(asyncResp, *assetTag);
2572 }
James Feistb49ac872019-05-21 15:12:01 -07002573
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002574 if (wdtTimerProps)
2575 {
2576 std::optional<bool> wdtEnable;
2577 std::optional<std::string> wdtTimeOutAction;
2578
2579 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
2580 "FunctionEnabled", wdtEnable,
2581 "TimeoutAction", wdtTimeOutAction))
2582 {
2583 return;
2584 }
2585 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
2586 }
2587
2588 if (bootProps)
2589 {
2590 std::optional<std::string> bootSource;
2591 std::optional<std::string> bootEnable;
2592 std::optional<std::string> automaticRetryConfig;
2593
2594 if (!json_util::readJson(
2595 *bootProps, asyncResp->res,
2596 "BootSourceOverrideTarget", bootSource,
2597 "BootSourceOverrideEnabled", bootEnable,
2598 "AutomaticRetryConfig", automaticRetryConfig))
2599 {
2600 return;
2601 }
2602 if (bootSource || bootEnable)
2603 {
2604 setBootSourceProperties(asyncResp,
2605 std::move(bootSource),
2606 std::move(bootEnable));
2607 }
2608 if (automaticRetryConfig)
2609 {
2610 setAutomaticRetry(asyncResp, *automaticRetryConfig);
2611 }
2612 }
2613
2614 if (locationIndicatorActive)
2615 {
2616 setLocationIndicatorActive(asyncResp,
2617 *locationIndicatorActive);
2618 }
2619
2620 // TODO (Gunnar): Remove IndicatorLED after enough time has
2621 // passed
2622 if (indicatorLed)
2623 {
2624 setIndicatorLedState(asyncResp, *indicatorLed);
2625 asyncResp->res.addHeader(
2626 boost::beast::http::field::warning,
2627 "299 - \"IndicatorLED is deprecated. Use "
2628 "LocationIndicatorActive instead.\"");
2629 }
2630
2631 if (powerRestorePolicy)
2632 {
2633 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
2634 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002635
2636 if (powerMode)
2637 {
2638 setPowerMode(asyncResp, *powerMode);
2639 }
zhanghch058d1b46d2021-04-01 11:18:24 +08002640 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002641}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302642
2643/**
2644 * SystemResetActionInfo derived class for delivering Computer Systems
2645 * ResetType AllowableValues using ResetInfo schema.
2646 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002647inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302648{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302649
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302650 /**
2651 * Functions triggers appropriate requests on DBus
2652 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002653 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07002654 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002655 .methods(boost::beast::http::verb::get)(
2656 [](const crow::Request&,
2657 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2658 asyncResp->res.jsonValue = {
2659 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
2660 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
2661 {"Name", "Reset Action Info"},
2662 {"Id", "ResetActionInfo"},
2663 {"Parameters",
2664 {{{"Name", "ResetType"},
2665 {"Required", true},
2666 {"DataType", "String"},
2667 {"AllowableValues",
2668 {"On", "ForceOff", "ForceOn", "ForceRestart",
2669 "GracefulRestart", "GracefulShutdown", "PowerCycle",
2670 "Nmi"}}}}}};
2671 });
2672}
Ed Tanous1abe55e2018-09-05 08:30:59 -07002673} // namespace redfish