blob: 3e7b4739face4667a7be0948ce2b03729928b919 [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>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060025#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020026#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050027
Ed Tanousabf2add2019-01-22 16:40:12 -080028#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace redfish
31{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020032
Alpana Kumari9d3ae102019-04-12 06:49:32 -050033/**
34 * @brief Updates the Functional State of DIMMs
35 *
36 * @param[in] aResp Shared pointer for completing asynchronous calls
37 * @param[in] dimmState Dimm's Functional state, true/false
38 *
39 * @return None.
40 */
zhanghch058d1b46d2021-04-01 11:18:24 +080041inline void
42 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
43 const std::variant<bool>& dimmState)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050044{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050045 const bool* isDimmFunctional = std::get_if<bool>(&dimmState);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050046 if (isDimmFunctional == nullptr)
47 {
48 messages::internalError(aResp->res);
49 return;
50 }
Gunnar Mills698654b2019-10-16 13:17:37 -050051 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052
Gunnar Mills4e0453b2020-07-08 14:00:30 -050053 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050054 // Update STATE only if previous State was DISABLED and current Dimm is
55 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050056 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050057 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
58 if (prevMemSummary == "Disabled")
59 {
60 if (*isDimmFunctional == true)
61 {
62 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
63 "Enabled";
64 }
65 }
66}
67
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050068/*
69 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
70 *
71 * @param[in] aResp Shared pointer for completing asynchronous calls
72 * @param[in] cpuPresenceState CPU present or not
73 *
74 * @return None.
75 */
zhanghch058d1b46d2021-04-01 11:18:24 +080076inline void
77 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
78 const std::variant<bool>& cpuPresenceState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050080 const bool* isCpuPresent = std::get_if<bool>(&cpuPresenceState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081
82 if (isCpuPresent == nullptr)
83 {
84 messages::internalError(aResp->res);
85 return;
86 }
Gunnar Mills698654b2019-10-16 13:17:37 -050087 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050088
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050089 if (*isCpuPresent == true)
90 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050091 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080092 aResp->res.jsonValue["ProcessorSummary"]["Count"];
93 auto procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050094 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080095 if (procCountPtr != nullptr)
96 {
97 // shouldn't be possible to be nullptr
98 *procCountPtr += 1;
99 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500100 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500101}
102
103/*
104 * @brief Update "ProcessorSummary" "Status" "State" based on
105 * CPU Functional State
106 *
107 * @param[in] aResp Shared pointer for completing asynchronous calls
108 * @param[in] cpuFunctionalState is CPU functional true/false
109 *
110 * @return None.
111 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000112inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800113 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000114 const std::variant<bool>& cpuFunctionalState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500115{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500116 const bool* isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500117
118 if (isCpuFunctional == nullptr)
119 {
120 messages::internalError(aResp->res);
121 return;
122 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500123 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500124
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500125 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500126 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
127
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500128 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500129 // Update STATE only if previous State was Non_Functional and current CPU is
130 // Functional.
131 if (prevProcState == "Disabled")
132 {
133 if (*isCpuFunctional == true)
134 {
135 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
136 "Enabled";
137 }
138 }
139}
140
141/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700142 * @brief Retrieves computer system properties over dbus
143 *
144 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500145 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700146 *
147 * @return None.
148 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700149inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800150 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700151 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700152{
Ed Tanous6c34de42018-08-29 13:37:36 -0700153 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500154
Ed Tanous6c34de42018-08-29 13:37:36 -0700155 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700156 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700157 const boost::system::error_code ec,
158 const std::vector<std::pair<
159 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500160 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
161 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700162 if (ec)
163 {
164 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700165 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700166 return;
167 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700168 // Iterate over all retrieved ObjectPaths.
169 for (const std::pair<std::string,
170 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500171 std::string, std::vector<std::string>>>>&
172 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700173 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500174 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700175 BMCWEB_LOG_DEBUG << "Got path: " << path;
176 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500177 std::pair<std::string, std::vector<std::string>>>&
178 connectionNames = object.second;
Ed Tanous6c34de42018-08-29 13:37:36 -0700179 if (connectionNames.size() < 1)
180 {
181 continue;
182 }
Ed Tanous029573d2019-02-01 10:57:49 -0800183
James Feist5bc2dc82019-10-22 14:33:16 -0700184 auto memoryHealth = std::make_shared<HealthPopulate>(
185 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
186
187 auto cpuHealth = std::make_shared<HealthPopulate>(
188 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
189
190 systemHealth->children.emplace_back(memoryHealth);
191 systemHealth->children.emplace_back(cpuHealth);
192
Ed Tanous029573d2019-02-01 10:57:49 -0800193 // This is not system, so check if it's cpu, dimm, UUID or
194 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500195 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700196 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500197 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700198 {
Ed Tanous029573d2019-02-01 10:57:49 -0800199 if (interfaceName ==
200 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700201 {
Ed Tanous029573d2019-02-01 10:57:49 -0800202 BMCWEB_LOG_DEBUG
203 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500204
Ed Tanous029573d2019-02-01 10:57:49 -0800205 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500206 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700207 path](const boost::system::error_code ec2,
208 const std::vector<
209 std::pair<std::string, VariantType>>&
210 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000211 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800212 {
213 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000214 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800215 messages::internalError(aResp->res);
216 return;
217 }
218 BMCWEB_LOG_DEBUG << "Got "
219 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500220 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500221
222 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800223 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500224 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500225 VariantType>&
226 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700227 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800228 if (property.first !=
229 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700230 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800231 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700232 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500233 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500234 std::get_if<uint32_t>(
235 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800236 if (value == nullptr)
237 {
238 BMCWEB_LOG_DEBUG
239 << "Find incorrect type of "
240 "MemorySize";
241 continue;
242 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500243 nlohmann::json& totalMemory =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800244 aResp->res
245 .jsonValue["MemorySummar"
246 "y"]
247 ["TotalSystemMe"
248 "moryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500249 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800250 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500251 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800252 if (preValue == nullptr)
253 {
254 continue;
255 }
256 aResp->res
257 .jsonValue["MemorySummary"]
258 ["TotalSystemMemoryGi"
259 "B"] =
260 *value / (1024 * 1024) +
261 *preValue;
262 aResp->res
263 .jsonValue["MemorySummary"]
264 ["Status"]["State"] =
265 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 }
Ed Tanous029573d2019-02-01 10:57:49 -0800267 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500268 else
269 {
270 auto getDimmProperties =
271 [aResp](
272 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000273 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500274 const std::variant<bool>&
275 dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000276 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500277 {
278 BMCWEB_LOG_ERROR
279 << "DBUS response "
280 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000281 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500282 return;
283 }
284 updateDimmProperties(aResp,
285 dimmState);
286 };
287 crow::connections::systemBus
288 ->async_method_call(
289 std::move(getDimmProperties),
290 service, path,
291 "org.freedesktop.DBus."
292 "Properties",
293 "Get",
294 "xyz.openbmc_project.State."
295 "Decorator.OperationalStatus",
296 "Functional");
297 }
Ed Tanous029573d2019-02-01 10:57:49 -0800298 },
299 connection.first, path,
300 "org.freedesktop.DBus.Properties", "GetAll",
301 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700302
303 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800304 }
305 else if (interfaceName ==
306 "xyz.openbmc_project.Inventory.Item.Cpu")
307 {
308 BMCWEB_LOG_DEBUG
309 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500310
Ed Tanous029573d2019-02-01 10:57:49 -0800311 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500312 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700313 path](const boost::system::error_code ec2,
314 const std::vector<
315 std::pair<std::string, VariantType>>&
316 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000317 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800318 {
319 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000320 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800321 messages::internalError(aResp->res);
322 return;
323 }
324 BMCWEB_LOG_DEBUG << "Got "
325 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500326 << " Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700327
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500328 if (properties.size() > 0)
329 {
Zhikui Ren9cf21522020-09-10 11:13:14 -0700330 const uint64_t* processorId = nullptr;
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700331 const std::string* procFamily = nullptr;
332 nlohmann::json& procSummary =
333 aResp->res.jsonValue["ProcessorSumm"
334 "ary"];
335 nlohmann::json& procCount =
336 procSummary["Count"];
337
338 auto procCountPtr = procCount.get_ptr<
339 nlohmann::json::
340 number_integer_t*>();
341 if (procCountPtr == nullptr)
342 {
343 messages::internalError(aResp->res);
344 return;
345 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500346 for (const auto& property : properties)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500347 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700348
Zhikui Ren9cf21522020-09-10 11:13:14 -0700349 if (property.first == "Id")
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700350 {
351 processorId =
Zhikui Ren9cf21522020-09-10 11:13:14 -0700352 std::get_if<uint64_t>(
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700353 &property.second);
354 if (nullptr != procFamily)
Ed Tanous3174e4d2020-10-07 11:41:22 -0700355 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700356 break;
Ed Tanous3174e4d2020-10-07 11:41:22 -0700357 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700358 continue;
359 }
360
Zhikui Ren9cf21522020-09-10 11:13:14 -0700361 if (property.first == "Family")
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500362 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700363 procFamily =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500364 std::get_if<std::string>(
365 &property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700366 if (nullptr != processorId)
Ed Tanous3174e4d2020-10-07 11:41:22 -0700367 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700368 break;
Ed Tanous3174e4d2020-10-07 11:41:22 -0700369 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700370 continue;
371 }
372 }
James Feistb4b95952019-12-05 15:01:55 -0800373
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700374 if (procFamily != nullptr &&
375 processorId != nullptr)
376 {
377 if (procCountPtr != nullptr &&
378 *processorId != 0)
379 {
380 *procCountPtr += 1;
381 procSummary["Status"]["State"] =
382 "Enabled";
383
384 procSummary["Model"] =
385 *procFamily;
Ed Tanous6c34de42018-08-29 13:37:36 -0700386 }
387 }
Ed Tanous029573d2019-02-01 10:57:49 -0800388 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500389 else
390 {
391 auto getCpuPresenceState =
392 [aResp](
393 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000394 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500395 const std::variant<bool>&
396 cpuPresenceCheck) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000397 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500398 {
399 BMCWEB_LOG_ERROR
400 << "DBUS response "
401 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000402 << ec3;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500403 return;
404 }
405 modifyCpuPresenceState(
406 aResp, cpuPresenceCheck);
407 };
408
409 auto getCpuFunctionalState =
410 [aResp](
411 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000412 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500413 const std::variant<bool>&
414 cpuFunctionalCheck) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000415 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500416 {
417 BMCWEB_LOG_ERROR
418 << "DBUS response "
419 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000420 << ec3;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500421 return;
422 }
423 modifyCpuFunctionalState(
424 aResp, cpuFunctionalCheck);
425 };
426 // Get the Presence of CPU
427 crow::connections::systemBus
428 ->async_method_call(
429 std::move(getCpuPresenceState),
430 service, path,
431 "org.freedesktop.DBus."
432 "Properties",
433 "Get",
434 "xyz.openbmc_project.Inventory."
435 "Item",
436 "Present");
437
438 // Get the Functional State
439 crow::connections::systemBus
440 ->async_method_call(
441 std::move(
442 getCpuFunctionalState),
443 service, path,
444 "org.freedesktop.DBus."
445 "Properties",
446 "Get",
447 "xyz.openbmc_project.State."
448 "Decorator."
449 "OperationalStatus",
450 "Functional");
451
452 // Get the MODEL from
453 // xyz.openbmc_project.Inventory.Decorator.Asset
454 // support it later as Model is Empty
455 // currently.
456 }
Ed Tanous029573d2019-02-01 10:57:49 -0800457 },
458 connection.first, path,
459 "org.freedesktop.DBus.Properties", "GetAll",
460 "xyz.openbmc_project.Inventory.Item.Cpu");
James Feist5bc2dc82019-10-22 14:33:16 -0700461
462 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800463 }
464 else if (interfaceName ==
465 "xyz.openbmc_project.Common.UUID")
466 {
467 BMCWEB_LOG_DEBUG
468 << "Found UUID, now get its properties.";
469 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500470 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000471 const boost::system::error_code ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500472 const std::vector<
473 std::pair<std::string, VariantType>>&
474 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000475 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800476 {
477 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000478 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800479 messages::internalError(aResp->res);
480 return;
481 }
482 BMCWEB_LOG_DEBUG << "Got "
483 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500484 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800485 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500486 VariantType>&
487 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800488 {
Ed Tanous029573d2019-02-01 10:57:49 -0800489 if (property.first == "UUID")
490 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500491 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500492 std::get_if<std::string>(
493 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700494
Ed Tanous029573d2019-02-01 10:57:49 -0800495 if (value != nullptr)
496 {
497 std::string valueStr = *value;
498 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700499 {
Ed Tanous029573d2019-02-01 10:57:49 -0800500 valueStr.insert(8, 1, '-');
501 valueStr.insert(13, 1, '-');
502 valueStr.insert(18, 1, '-');
503 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700504 }
Ed Tanous029573d2019-02-01 10:57:49 -0800505 BMCWEB_LOG_DEBUG << "UUID = "
506 << valueStr;
507 aResp->res.jsonValue["UUID"] =
508 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700509 }
510 }
Ed Tanous029573d2019-02-01 10:57:49 -0800511 }
512 },
513 connection.first, path,
514 "org.freedesktop.DBus.Properties", "GetAll",
515 "xyz.openbmc_project.Common.UUID");
516 }
517 else if (interfaceName ==
518 "xyz.openbmc_project.Inventory.Item.System")
519 {
520 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500521 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000522 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500523 const std::vector<
524 std::pair<std::string, VariantType>>&
525 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000526 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800527 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700528 // doesn't have to include this
529 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800530 return;
531 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500532 BMCWEB_LOG_DEBUG
533 << "Got " << propertiesList.size()
534 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800535 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500536 VariantType>&
537 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800538 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500539 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600540 property.first;
541 if ((propertyName == "PartNumber") ||
542 (propertyName == "SerialNumber") ||
543 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500544 (propertyName == "Model") ||
545 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800546 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500547 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600548 std::get_if<std::string>(
549 &property.second);
550 if (value != nullptr)
551 {
552 aResp->res
553 .jsonValue[propertyName] =
554 *value;
555 }
Ed Tanous029573d2019-02-01 10:57:49 -0800556 }
557 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500558
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600559 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500560 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600561 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500562 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800563 },
564 connection.first, path,
565 "org.freedesktop.DBus.Properties", "GetAll",
566 "xyz.openbmc_project.Inventory.Decorator."
567 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700568
569 crow::connections::systemBus->async_method_call(
570 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000571 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500572 const std::variant<std::string>& property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000573 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700574 {
575 // doesn't have to include this
576 // interface
577 return;
578 }
579
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500580 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700581 std::get_if<std::string>(&property);
582 if (value != nullptr)
583 {
584 aResp->res.jsonValue["AssetTag"] =
585 *value;
586 }
587 },
588 connection.first, path,
589 "org.freedesktop.DBus.Properties", "Get",
590 "xyz.openbmc_project.Inventory.Decorator."
591 "AssetTag",
592 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700593 }
594 }
595 }
596 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700597 },
598 "xyz.openbmc_project.ObjectMapper",
599 "/xyz/openbmc_project/object_mapper",
600 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700601 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500602 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700603 "xyz.openbmc_project.Inventory.Decorator.Asset",
604 "xyz.openbmc_project.Inventory.Item.Cpu",
605 "xyz.openbmc_project.Inventory.Item.Dimm",
606 "xyz.openbmc_project.Inventory.Item.System",
607 "xyz.openbmc_project.Common.UUID",
608 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700609}
610
611/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700612 * @brief Retrieves host state properties over dbus
613 *
614 * @param[in] aResp Shared pointer for completing asynchronous calls.
615 *
616 * @return None.
617 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800618inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700619{
620 BMCWEB_LOG_DEBUG << "Get host information.";
621 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800622 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500623 const std::variant<std::string>& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700624 if (ec)
625 {
626 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700627 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700628 return;
629 }
Ed Tanous66173382018-08-15 18:20:59 -0700630
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500631 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700632 BMCWEB_LOG_DEBUG << "Host state: " << *s;
633 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700634 {
Ed Tanous66173382018-08-15 18:20:59 -0700635 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800636 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700637 {
Ed Tanous66173382018-08-15 18:20:59 -0700638 aResp->res.jsonValue["PowerState"] = "On";
639 aResp->res.jsonValue["Status"]["State"] = "Enabled";
640 }
Andrew Geissler83935af2020-02-13 10:24:53 -0600641 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Gunnar Mills8c888602020-05-01 14:25:09 -0500642 "Quiesced")
643 {
644 aResp->res.jsonValue["PowerState"] = "On";
645 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
646 }
647 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Andrew Geissler83935af2020-02-13 10:24:53 -0600648 "DiagnosticMode")
649 {
650 aResp->res.jsonValue["PowerState"] = "On";
651 aResp->res.jsonValue["Status"]["State"] = "InTest";
652 }
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600653 else if (*s == "xyz.openbmc_project.State.Host.HostState."
654 "TransitioningToRunning")
655 {
656 aResp->res.jsonValue["PowerState"] = "PoweringOn";
Noah Brewer15c27bf2021-04-27 15:24:25 -0500657 aResp->res.jsonValue["Status"]["State"] = "Starting";
Andrew Geissler1a2a1432021-01-06 13:48:57 -0600658 }
659 else if (*s == "xyz.openbmc_project.State.Host.HostState."
660 "TransitioningToOff")
661 {
662 aResp->res.jsonValue["PowerState"] = "PoweringOff";
663 aResp->res.jsonValue["Status"]["State"] = "Disabled";
664 }
Ed Tanous66173382018-08-15 18:20:59 -0700665 else
666 {
667 aResp->res.jsonValue["PowerState"] = "Off";
668 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700669 }
670 }
671 },
672 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700673 "org.freedesktop.DBus.Properties", "Get",
674 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700675}
676
677/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500678 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530679 *
680 * @param[in] dbusSource The boot source in DBUS speak.
681 *
682 * @return Returns as a string, the boot source in Redfish terms. If translation
683 * cannot be done, returns an empty string.
684 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000685inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686{
687 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
688 {
689 return "None";
690 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700691 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530692 {
693 return "Hdd";
694 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700695 if (dbusSource ==
696 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530697 {
698 return "Cd";
699 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700700 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530701 {
702 return "Pxe";
703 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700704 if (dbusSource ==
705 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700706 {
707 return "Usb";
708 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700709 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530710}
711
712/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500713 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530714 *
715 * @param[in] dbusMode The boot mode in DBUS speak.
716 *
717 * @return Returns as a string, the boot mode in Redfish terms. If translation
718 * cannot be done, returns an empty string.
719 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000720inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530721{
722 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
723 {
724 return "None";
725 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700726 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530727 {
728 return "Diags";
729 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700730 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 {
732 return "BiosSetup";
733 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700734 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530735}
736
737/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500738 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530739 *
740 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700741 * @param[out] bootSource The DBus source
742 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530743 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700744 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530745 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800746inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500747 const std::string& rfSource,
748 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530749{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700750 // The caller has initialized the bootSource and bootMode to:
751 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
752 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
753 // Only modify the bootSource/bootMode variable needed to achieve the
754 // desired boot action.
755
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530756 if (rfSource == "None")
757 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700758 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530759 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700760 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530761 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700762 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
763 }
764 else if (rfSource == "Hdd")
765 {
766 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
767 }
768 else if (rfSource == "Diags")
769 {
770 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
771 }
772 else if (rfSource == "Cd")
773 {
774 bootSource =
775 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
776 }
777 else if (rfSource == "BiosSetup")
778 {
779 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700781 else if (rfSource == "Usb")
782 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783 bootSource =
784 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700785 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530786 else
787 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700788 BMCWEB_LOG_DEBUG << "Invalid property value for "
789 "BootSourceOverrideTarget: "
790 << bootSource;
791 messages::propertyValueNotInList(aResp->res, rfSource,
792 "BootSourceTargetOverride");
793 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530794 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700795 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530796}
Ali Ahmed19817712021-06-29 17:01:52 -0500797
Andrew Geissler978b8802020-11-19 13:36:40 -0600798/**
799 * @brief Retrieves boot progress of the system
800 *
801 * @param[in] aResp Shared pointer for generating response message.
802 *
803 * @return None.
804 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800805inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600806{
807 crow::connections::systemBus->async_method_call(
808 [aResp](const boost::system::error_code ec,
809 const std::variant<std::string>& bootProgress) {
810 if (ec)
811 {
812 // BootProgress is an optional object so just do nothing if
813 // not found
814 return;
815 }
816
817 const std::string* bootProgressStr =
818 std::get_if<std::string>(&bootProgress);
819
820 if (!bootProgressStr)
821 {
822 // Interface implemented but property not found, return error
823 // for that
824 messages::internalError(aResp->res);
825 return;
826 }
827
828 BMCWEB_LOG_DEBUG << "Boot Progress: " << *bootProgressStr;
829
830 // Now convert the D-Bus BootProgress to the appropriate Redfish
831 // enum
832 std::string rfBpLastState = "None";
833 if (*bootProgressStr == "xyz.openbmc_project.State.Boot.Progress."
834 "ProgressStages.Unspecified")
835 {
836 rfBpLastState = "None";
837 }
838 else if (*bootProgressStr ==
839 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
840 "PrimaryProcInit")
841 {
842 rfBpLastState = "PrimaryProcessorInitializationStarted";
843 }
844 else if (*bootProgressStr ==
845 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
846 "BusInit")
847 {
848 rfBpLastState = "BusInitializationStarted";
849 }
850 else if (*bootProgressStr ==
851 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
852 "MemoryInit")
853 {
854 rfBpLastState = "MemoryInitializationStarted";
855 }
856 else if (*bootProgressStr ==
857 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
858 "SecondaryProcInit")
859 {
860 rfBpLastState = "SecondaryProcessorInitializationStarted";
861 }
862 else if (*bootProgressStr ==
863 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
864 "PCIInit")
865 {
866 rfBpLastState = "PCIResourceConfigStarted";
867 }
868 else if (*bootProgressStr ==
869 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
870 "SystemInitComplete")
871 {
872 rfBpLastState = "SystemHardwareInitializationComplete";
873 }
874 else if (*bootProgressStr ==
875 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
876 "OSStart")
877 {
878 rfBpLastState = "OSBootStarted";
879 }
880 else if (*bootProgressStr ==
881 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
882 "OSRunning")
883 {
884 rfBpLastState = "OSRunning";
885 }
886 else
887 {
888 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
889 << *bootProgressStr;
890 // Just return the default
891 }
892
893 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
894 },
895 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
896 "org.freedesktop.DBus.Properties", "Get",
897 "xyz.openbmc_project.State.Boot.Progress", "BootProgress");
898}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530899
900/**
901 * @brief Retrieves boot mode over DBUS and fills out the response
902 *
903 * @param[in] aResp Shared pointer for generating response message.
904 * @param[in] bootDbusObj The dbus object to query for boot properties.
905 *
906 * @return None.
907 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800908inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700909 const std::string& bootDbusObj)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530910{
911 crow::connections::systemBus->async_method_call(
912 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500913 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530914 if (ec)
915 {
916 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
917 messages::internalError(aResp->res);
918 return;
919 }
920
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500921 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530922 std::get_if<std::string>(&bootMode);
923
924 if (!bootModeStr)
925 {
926 messages::internalError(aResp->res);
927 return;
928 }
929
930 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
931
932 // TODO (Santosh): Do we need to support override mode?
933 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
934 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
935 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700936 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530937
938 if (*bootModeStr !=
939 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
940 {
941 auto rfMode = dbusToRfBootMode(*bootModeStr);
942 if (!rfMode.empty())
943 {
944 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
945 rfMode;
946 }
947 }
948
949 // If the BootSourceOverrideTarget is still "None" at the end,
950 // reset the BootSourceOverrideEnabled to indicate that
951 // overrides are disabled
952 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
953 "None")
954 {
955 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
956 "Disabled";
957 }
958 },
959 "xyz.openbmc_project.Settings", bootDbusObj,
960 "org.freedesktop.DBus.Properties", "Get",
961 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
962}
963
964/**
965 * @brief Retrieves boot source over DBUS
966 *
967 * @param[in] aResp Shared pointer for generating response message.
968 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
969 *
970 * @return None.
971 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800972inline void getBootSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -0700973 bool oneTimeEnabled)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974{
975 std::string bootDbusObj =
976 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
977 : "/xyz/openbmc_project/control/host0/boot";
978
979 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
980 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
981 (oneTimeEnabled) ? "Once" : "Continuous";
982
983 crow::connections::systemBus->async_method_call(
984 [aResp, bootDbusObj](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500985 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986 if (ec)
987 {
988 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
989 messages::internalError(aResp->res);
990 return;
991 }
992
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500993 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530994 std::get_if<std::string>(&bootSource);
995
996 if (!bootSourceStr)
997 {
998 messages::internalError(aResp->res);
999 return;
1000 }
1001 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
1002
1003 auto rfSource = dbusToRfBootSource(*bootSourceStr);
1004 if (!rfSource.empty())
1005 {
1006 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1007 rfSource;
1008 }
1009 },
1010 "xyz.openbmc_project.Settings", bootDbusObj,
1011 "org.freedesktop.DBus.Properties", "Get",
1012 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Ed Tanousf23b7292020-10-15 09:41:17 -07001013 getBootMode(aResp, bootDbusObj);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301014}
1015
1016/**
1017 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1018 * get boot source and boot mode.
1019 *
1020 * @param[in] aResp Shared pointer for generating response message.
1021 *
1022 * @return None.
1023 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001024inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301025{
1026 BMCWEB_LOG_DEBUG << "Get boot information.";
1027
1028 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001029 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001030 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301031 if (ec)
1032 {
1033 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -07001034 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301035 return;
1036 }
1037
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001038 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301039
1040 if (!oneTimePtr)
1041 {
1042 messages::internalError(aResp->res);
1043 return;
1044 }
1045 getBootSource(aResp, *oneTimePtr);
1046 },
1047 "xyz.openbmc_project.Settings",
1048 "/xyz/openbmc_project/control/host0/boot/one_time",
1049 "org.freedesktop.DBus.Properties", "Get",
1050 "xyz.openbmc_project.Object.Enable", "Enabled");
1051}
1052
1053/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001054 * @brief Retrieves the Last Reset Time
1055 *
1056 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1057 * and power off. Even though this is the "system" Redfish object look at the
1058 * chassis D-Bus interface for the LastStateChangeTime since this has the
1059 * last power operation time.
1060 *
1061 * @param[in] aResp Shared pointer for generating response message.
1062 *
1063 * @return None.
1064 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001065inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001066{
1067 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1068
1069 crow::connections::systemBus->async_method_call(
1070 [aResp](const boost::system::error_code ec,
1071 std::variant<uint64_t>& lastResetTime) {
1072 if (ec)
1073 {
1074 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1075 return;
1076 }
1077
1078 const uint64_t* lastResetTimePtr =
1079 std::get_if<uint64_t>(&lastResetTime);
1080
1081 if (!lastResetTimePtr)
1082 {
1083 messages::internalError(aResp->res);
1084 return;
1085 }
1086 // LastStateChangeTime is epoch time, in milliseconds
1087 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1088 time_t lastResetTimeStamp =
1089 static_cast<time_t>(*lastResetTimePtr / 1000);
1090
1091 // Convert to ISO 8601 standard
1092 aResp->res.jsonValue["LastResetTime"] =
1093 crow::utility::getDateTime(lastResetTimeStamp);
1094 },
1095 "xyz.openbmc_project.State.Chassis",
1096 "/xyz/openbmc_project/state/chassis0",
1097 "org.freedesktop.DBus.Properties", "Get",
1098 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
1099}
1100
1101/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001102 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1103 *
1104 * @param[in] aResp Shared pointer for generating response message.
1105 *
1106 * @return None.
1107 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001108inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001109{
1110 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1111
1112 crow::connections::systemBus->async_method_call(
1113 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001114 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001115 if (ec)
1116 {
1117 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1118 return;
1119 }
1120
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001121 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001122 std::get_if<bool>(&autoRebootEnabled);
1123
1124 if (!autoRebootEnabledPtr)
1125 {
1126 messages::internalError(aResp->res);
1127 return;
1128 }
1129
1130 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1131 if (*autoRebootEnabledPtr == true)
1132 {
1133 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1134 "RetryAttempts";
1135 // If AutomaticRetry (AutoReboot) is enabled see how many
1136 // attempts are left
1137 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001138 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001139 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001140 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001141 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001142 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001143 return;
1144 }
1145
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001146 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001147 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1148
1149 if (!autoRebootAttemptsLeftPtr)
1150 {
1151 messages::internalError(aResp->res);
1152 return;
1153 }
1154
1155 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1156 << *autoRebootAttemptsLeftPtr;
1157
1158 aResp->res
1159 .jsonValue["Boot"]
1160 ["RemainingAutomaticRetryAttempts"] =
1161 *autoRebootAttemptsLeftPtr;
1162 },
1163 "xyz.openbmc_project.State.Host",
1164 "/xyz/openbmc_project/state/host0",
1165 "org.freedesktop.DBus.Properties", "Get",
1166 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1167 "AttemptsLeft");
1168 }
1169 else
1170 {
1171 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1172 "Disabled";
1173 }
1174
1175 // Not on D-Bus. Hardcoded here:
1176 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1177 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001178
1179 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1180 // and RetryAttempts. OpenBMC only supports Disabled and
1181 // RetryAttempts.
1182 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1183 "AllowableValues"] = {"Disabled",
1184 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001185 },
1186 "xyz.openbmc_project.Settings",
1187 "/xyz/openbmc_project/control/host0/auto_reboot",
1188 "org.freedesktop.DBus.Properties", "Get",
1189 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1190}
1191
1192/**
George Liuc6a620f2020-04-10 17:18:11 +08001193 * @brief Retrieves power restore policy over DBUS.
1194 *
1195 * @param[in] aResp Shared pointer for generating response message.
1196 *
1197 * @return None.
1198 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001199inline void
1200 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001201{
1202 BMCWEB_LOG_DEBUG << "Get power restore policy";
1203
1204 crow::connections::systemBus->async_method_call(
1205 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001206 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001207 if (ec)
1208 {
1209 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1210 return;
1211 }
1212
1213 const boost::container::flat_map<std::string, std::string>
1214 policyMaps = {
1215 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1216 "AlwaysOn",
1217 "AlwaysOn"},
1218 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1219 "AlwaysOff",
1220 "AlwaysOff"},
1221 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001222 "Restore",
George Liuc6a620f2020-04-10 17:18:11 +08001223 "LastState"}};
1224
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001225 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001226
1227 if (!policyPtr)
1228 {
1229 messages::internalError(aResp->res);
1230 return;
1231 }
1232
1233 auto policyMapsIt = policyMaps.find(*policyPtr);
1234 if (policyMapsIt == policyMaps.end())
1235 {
1236 messages::internalError(aResp->res);
1237 return;
1238 }
1239
1240 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1241 },
1242 "xyz.openbmc_project.Settings",
1243 "/xyz/openbmc_project/control/host0/power_restore_policy",
1244 "org.freedesktop.DBus.Properties", "Get",
1245 "xyz.openbmc_project.Control.Power.RestorePolicy",
1246 "PowerRestorePolicy");
1247}
1248
1249/**
Ali Ahmed19817712021-06-29 17:01:52 -05001250 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1251 * TPM is required for booting the host.
1252 *
1253 * @param[in] aResp Shared pointer for generating response message.
1254 *
1255 * @return None.
1256 */
1257inline void getTrustedModuleRequiredToBoot(
1258 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1259{
1260 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1261
1262 crow::connections::systemBus->async_method_call(
1263 [aResp](
1264 const boost::system::error_code ec,
1265 std::vector<std::pair<
1266 std::string,
1267 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1268 subtree) {
1269 if (ec)
1270 {
1271 BMCWEB_LOG_DEBUG
1272 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1273 // This is an optional D-Bus object so just return if
1274 // error occurs
1275 return;
1276 }
1277 if (subtree.size() == 0)
1278 {
1279 // As noted above, this is an optional interface so just return
1280 // if there is no instance found
1281 return;
1282 }
1283
1284 /* When there is more than one TPMEnable object... */
1285 if (subtree.size() > 1)
1286 {
1287 BMCWEB_LOG_DEBUG
1288 << "DBUS response has more than 1 TPM Enable object:"
1289 << subtree.size();
1290 // Throw an internal Error and return
1291 messages::internalError(aResp->res);
1292 return;
1293 }
1294
1295 // Make sure the Dbus response map has a service and objectPath
1296 // field
1297 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1298 {
1299 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1300 messages::internalError(aResp->res);
1301 return;
1302 }
1303
1304 const std::string& path = subtree[0].first;
1305 const std::string& serv = subtree[0].second.begin()->first;
1306
1307 // Valid TPM Enable object found, now reading the current value
1308 crow::connections::systemBus->async_method_call(
1309 [aResp](const boost::system::error_code ec,
1310 std::variant<bool>& tpmRequired) {
1311 if (ec)
1312 {
1313 BMCWEB_LOG_DEBUG
1314 << "D-BUS response error on TPM.Policy Get" << ec;
1315 messages::internalError(aResp->res);
1316 return;
1317 }
1318
1319 const bool* tpmRequiredVal =
1320 std::get_if<bool>(&tpmRequired);
1321
1322 if (!tpmRequiredVal)
1323 {
1324 messages::internalError(aResp->res);
1325 return;
1326 }
1327
1328 if (*tpmRequiredVal == true)
1329 {
1330 aResp->res
1331 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1332 "Required";
1333 }
1334 else
1335 {
1336 aResp->res
1337 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1338 "Disabled";
1339 }
1340 },
1341 serv, path, "org.freedesktop.DBus.Properties", "Get",
1342 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable");
1343 },
1344 "xyz.openbmc_project.ObjectMapper",
1345 "/xyz/openbmc_project/object_mapper",
1346 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1347 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1348}
1349
1350/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301351 * @brief Sets boot properties into DBUS object(s).
1352 *
1353 * @param[in] aResp Shared pointer for generating response message.
1354 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
1355 * @param[in] bootSource The boot source to set.
1356 * @param[in] bootEnable The source override "enable" to set.
1357 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001358 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301359 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001360inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301361 bool oneTimeEnabled,
Ed Tanousf23b7292020-10-15 09:41:17 -07001362 const std::optional<std::string>& bootSource,
1363 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301364{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001365 std::string bootSourceStr =
1366 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1367 std::string bootModeStr =
1368 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301369 bool oneTimeSetting = oneTimeEnabled;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001370 bool useBootSource = true;
1371
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301372 // Validate incoming parameters
1373 if (bootEnable)
1374 {
1375 if (*bootEnable == "Once")
1376 {
1377 oneTimeSetting = true;
1378 }
1379 else if (*bootEnable == "Continuous")
1380 {
1381 oneTimeSetting = false;
1382 }
1383 else if (*bootEnable == "Disabled")
1384 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001385 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301386 oneTimeSetting = false;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001387 useBootSource = false;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301388 }
1389 else
1390 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301391 BMCWEB_LOG_DEBUG << "Unsupported value for "
1392 "BootSourceOverrideEnabled: "
1393 << *bootEnable;
1394 messages::propertyValueNotInList(aResp->res, *bootEnable,
1395 "BootSourceOverrideEnabled");
1396 return;
1397 }
1398 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301399
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001400 if (bootSource && useBootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301401 {
1402 // Source target specified
1403 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1404 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001405 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1406 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301407 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001408 BMCWEB_LOG_DEBUG
1409 << "Invalid property value for BootSourceOverrideTarget: "
1410 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301411 messages::propertyValueNotInList(aResp->res, *bootSource,
1412 "BootSourceTargetOverride");
1413 return;
1414 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001415 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301416
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001417 // Act on validated parameters
1418 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1419 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001420 const char* bootObj =
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001421 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1422 : "/xyz/openbmc_project/control/host0/boot";
1423
1424 crow::connections::systemBus->async_method_call(
1425 [aResp](const boost::system::error_code ec) {
1426 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301427 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001428 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1429 messages::internalError(aResp->res);
1430 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301431 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001432 BMCWEB_LOG_DEBUG << "Boot source update done.";
1433 },
1434 "xyz.openbmc_project.Settings", bootObj,
1435 "org.freedesktop.DBus.Properties", "Set",
1436 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1437 std::variant<std::string>(bootSourceStr));
1438
1439 crow::connections::systemBus->async_method_call(
1440 [aResp](const boost::system::error_code ec) {
1441 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301442 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001443 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1444 messages::internalError(aResp->res);
1445 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301446 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001447 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1448 },
1449 "xyz.openbmc_project.Settings", bootObj,
1450 "org.freedesktop.DBus.Properties", "Set",
1451 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1452 std::variant<std::string>(bootModeStr));
1453
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301454 crow::connections::systemBus->async_method_call(
1455 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1456 if (ec)
1457 {
1458 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1459 messages::internalError(aResp->res);
1460 return;
1461 }
1462 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1463 },
1464 "xyz.openbmc_project.Settings",
1465 "/xyz/openbmc_project/control/host0/boot/one_time",
1466 "org.freedesktop.DBus.Properties", "Set",
1467 "xyz.openbmc_project.Object.Enable", "Enabled",
1468 std::variant<bool>(oneTimeSetting));
1469}
1470
1471/**
1472 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1473 * set boot source/boot mode properties.
1474 *
1475 * @param[in] aResp Shared pointer for generating response message.
1476 * @param[in] bootSource The boot source from incoming RF request.
1477 * @param[in] bootEnable The boot override enable from incoming RF request.
1478 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001479 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301480 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001481inline void
1482 setBootSourceProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1483 std::optional<std::string> bootSource,
1484 std::optional<std::string> bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301485{
1486 BMCWEB_LOG_DEBUG << "Set boot information.";
1487
1488 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001489 [aResp, bootSource{std::move(bootSource)},
Patrick Williams19bd78d2020-05-13 17:38:24 -05001490 bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001491 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301492 if (ec)
1493 {
1494 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1495 messages::internalError(aResp->res);
1496 return;
1497 }
1498
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001499 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301500
1501 if (!oneTimePtr)
1502 {
1503 messages::internalError(aResp->res);
1504 return;
1505 }
1506
1507 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1508
Ed Tanousf23b7292020-10-15 09:41:17 -07001509 setBootModeOrSource(aResp, *oneTimePtr, bootSource, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301510 },
1511 "xyz.openbmc_project.Settings",
1512 "/xyz/openbmc_project/control/host0/boot/one_time",
1513 "org.freedesktop.DBus.Properties", "Get",
1514 "xyz.openbmc_project.Object.Enable", "Enabled");
1515}
1516
George Liuc6a620f2020-04-10 17:18:11 +08001517/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001518 * @brief Sets AssetTag
1519 *
1520 * @param[in] aResp Shared pointer for generating response message.
1521 * @param[in] assetTag "AssetTag" from request.
1522 *
1523 * @return None.
1524 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001525inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001526 const std::string& assetTag)
1527{
1528 crow::connections::systemBus->async_method_call(
1529 [aResp, assetTag](
1530 const boost::system::error_code ec,
1531 const std::vector<std::pair<
1532 std::string,
1533 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1534 subtree) {
1535 if (ec)
1536 {
1537 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1538 messages::internalError(aResp->res);
1539 return;
1540 }
1541 if (subtree.size() == 0)
1542 {
1543 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1544 messages::internalError(aResp->res);
1545 return;
1546 }
1547 // Assume only 1 system D-Bus object
1548 // Throw an error if there is more than 1
1549 if (subtree.size() > 1)
1550 {
1551 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1552 messages::internalError(aResp->res);
1553 return;
1554 }
1555 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1556 {
1557 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1558 messages::internalError(aResp->res);
1559 return;
1560 }
1561
1562 const std::string& path = subtree[0].first;
1563 const std::string& service = subtree[0].second.begin()->first;
1564
1565 if (service.empty())
1566 {
1567 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1568 messages::internalError(aResp->res);
1569 return;
1570 }
1571
1572 crow::connections::systemBus->async_method_call(
1573 [aResp](const boost::system::error_code ec2) {
1574 if (ec2)
1575 {
1576 BMCWEB_LOG_DEBUG
1577 << "D-Bus response error on AssetTag Set " << ec2;
1578 messages::internalError(aResp->res);
1579 return;
1580 }
1581 },
1582 service, path, "org.freedesktop.DBus.Properties", "Set",
1583 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1584 std::variant<std::string>(assetTag));
1585 },
1586 "xyz.openbmc_project.ObjectMapper",
1587 "/xyz/openbmc_project/object_mapper",
1588 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1589 "/xyz/openbmc_project/inventory", int32_t(0),
1590 std::array<const char*, 1>{
1591 "xyz.openbmc_project.Inventory.Item.System"});
1592}
1593
1594/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001595 * @brief Sets automaticRetry (Auto Reboot)
1596 *
1597 * @param[in] aResp Shared pointer for generating response message.
1598 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1599 *
1600 * @return None.
1601 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001602inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001603 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001604{
1605 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1606
1607 // OpenBMC only supports "Disabled" and "RetryAttempts".
1608 bool autoRebootEnabled;
1609
1610 if (automaticRetryConfig == "Disabled")
1611 {
1612 autoRebootEnabled = false;
1613 }
1614 else if (automaticRetryConfig == "RetryAttempts")
1615 {
1616 autoRebootEnabled = true;
1617 }
1618 else
1619 {
1620 BMCWEB_LOG_DEBUG << "Invalid property value for "
1621 "AutomaticRetryConfig: "
1622 << automaticRetryConfig;
1623 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1624 "AutomaticRetryConfig");
1625 return;
1626 }
1627
1628 crow::connections::systemBus->async_method_call(
1629 [aResp](const boost::system::error_code ec) {
1630 if (ec)
1631 {
1632 messages::internalError(aResp->res);
1633 return;
1634 }
1635 },
1636 "xyz.openbmc_project.Settings",
1637 "/xyz/openbmc_project/control/host0/auto_reboot",
1638 "org.freedesktop.DBus.Properties", "Set",
1639 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1640 std::variant<bool>(autoRebootEnabled));
1641}
1642
1643/**
George Liuc6a620f2020-04-10 17:18:11 +08001644 * @brief Sets power restore policy properties.
1645 *
1646 * @param[in] aResp Shared pointer for generating response message.
1647 * @param[in] policy power restore policy properties from request.
1648 *
1649 * @return None.
1650 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001651inline void
1652 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1653 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001654{
1655 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1656
1657 const boost::container::flat_map<std::string, std::string> policyMaps = {
1658 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1659 "AlwaysOn"},
1660 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1661 "AlwaysOff"},
1662 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
Gunnar Mills37ec9072021-01-05 19:43:44 -06001663 "Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001664
1665 std::string powerRestorPolicy;
1666
Gunnar Mills4e69c902021-01-05 19:50:11 -06001667 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001668 if (policyMapsIt == policyMaps.end())
1669 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001670 messages::propertyValueNotInList(aResp->res, policy,
1671 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001672 return;
1673 }
1674
1675 powerRestorPolicy = policyMapsIt->second;
1676
1677 crow::connections::systemBus->async_method_call(
1678 [aResp](const boost::system::error_code ec) {
1679 if (ec)
1680 {
1681 messages::internalError(aResp->res);
1682 return;
1683 }
1684 },
1685 "xyz.openbmc_project.Settings",
1686 "/xyz/openbmc_project/control/host0/power_restore_policy",
1687 "org.freedesktop.DBus.Properties", "Set",
1688 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1689 std::variant<std::string>(powerRestorPolicy));
1690}
1691
AppaRao Pulia6349912019-10-18 17:16:08 +05301692#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1693/**
1694 * @brief Retrieves provisioning status
1695 *
1696 * @param[in] aResp Shared pointer for completing asynchronous calls.
1697 *
1698 * @return None.
1699 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001700inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301701{
1702 BMCWEB_LOG_DEBUG << "Get OEM information.";
1703 crow::connections::systemBus->async_method_call(
1704 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001705 const std::vector<std::pair<std::string, VariantType>>&
1706 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301707 nlohmann::json& oemPFR =
1708 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001709 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1710 "#OemComputerSystem.OpenBmc";
1711 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1712
AppaRao Pulia6349912019-10-18 17:16:08 +05301713 if (ec)
1714 {
1715 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301716 // not an error, don't have to have the interface
1717 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301718 return;
1719 }
1720
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001721 const bool* provState = nullptr;
1722 const bool* lockState = nullptr;
1723 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301724 propertiesList)
1725 {
1726 if (property.first == "UfmProvisioned")
1727 {
1728 provState = std::get_if<bool>(&property.second);
1729 }
1730 else if (property.first == "UfmLocked")
1731 {
1732 lockState = std::get_if<bool>(&property.second);
1733 }
1734 }
1735
1736 if ((provState == nullptr) || (lockState == nullptr))
1737 {
1738 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1739 messages::internalError(aResp->res);
1740 return;
1741 }
1742
AppaRao Pulia6349912019-10-18 17:16:08 +05301743 if (*provState == true)
1744 {
1745 if (*lockState == true)
1746 {
1747 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1748 }
1749 else
1750 {
1751 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1752 }
1753 }
1754 else
1755 {
1756 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1757 }
1758 },
1759 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1760 "org.freedesktop.DBus.Properties", "GetAll",
1761 "xyz.openbmc_project.PFR.Attributes");
1762}
1763#endif
1764
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301765/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001766 * @brief Translate the PowerMode to a response message.
1767 *
1768 * @param[in] aResp Shared pointer for generating response message.
1769 * @param[in] modeValue PowerMode value to be translated
1770 *
1771 * @return None.
1772 */
1773inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1774 const std::string& modeValue)
1775{
1776 std::string modeString;
1777
1778 if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1779 "PowerMode.Static")
1780 {
1781 aResp->res.jsonValue["PowerMode"] = "Static";
1782 }
1783 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1784 "PowerMode.MaximumPerformance")
1785 {
1786 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1787 }
1788 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1789 "PowerMode.PowerSaving")
1790 {
1791 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1792 }
1793 else if (modeValue == "xyz.openbmc_project.Control.Power.Mode."
1794 "PowerMode.OEM")
1795 {
1796 aResp->res.jsonValue["PowerMode"] = "OEM";
1797 }
1798 else
1799 {
1800 // Any other values would be invalid
1801 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1802 messages::internalError(aResp->res);
1803 }
1804}
1805
1806/**
1807 * @brief Retrieves system power mode
1808 *
1809 * @param[in] aResp Shared pointer for generating response message.
1810 *
1811 * @return None.
1812 */
1813inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1814{
1815 BMCWEB_LOG_DEBUG << "Get power mode.";
1816
1817 // Get Power Mode object path:
1818 crow::connections::systemBus->async_method_call(
1819 [aResp](
1820 const boost::system::error_code ec,
1821 const std::vector<std::pair<
1822 std::string,
1823 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1824 subtree) {
1825 if (ec)
1826 {
1827 BMCWEB_LOG_DEBUG
1828 << "DBUS response error on Power.Mode GetSubTree " << ec;
1829 // This is an optional D-Bus object so just return if
1830 // error occurs
1831 return;
1832 }
1833 if (subtree.empty())
1834 {
1835 // As noted above, this is an optional interface so just return
1836 // if there is no instance found
1837 return;
1838 }
1839 if (subtree.size() > 1)
1840 {
1841 // More then one PowerMode object is not supported and is an
1842 // error
1843 BMCWEB_LOG_DEBUG
1844 << "Found more than 1 system D-Bus Power.Mode objects: "
1845 << subtree.size();
1846 messages::internalError(aResp->res);
1847 return;
1848 }
1849 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1850 {
1851 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1852 messages::internalError(aResp->res);
1853 return;
1854 }
1855 const std::string& path = subtree[0].first;
1856 const std::string& service = subtree[0].second.begin()->first;
1857 if (service.empty())
1858 {
1859 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1860 messages::internalError(aResp->res);
1861 return;
1862 }
1863 // Valid Power Mode object found, now read the current value
1864 crow::connections::systemBus->async_method_call(
1865 [aResp](const boost::system::error_code ec,
1866 const std::variant<std::string>& pmode) {
1867 if (ec)
1868 {
1869 BMCWEB_LOG_DEBUG
1870 << "DBUS response error on PowerMode Get: " << ec;
1871 messages::internalError(aResp->res);
1872 return;
1873 }
1874
1875 const std::string* s = std::get_if<std::string>(&pmode);
1876 if (s == nullptr)
1877 {
1878 BMCWEB_LOG_DEBUG << "Unable to get PowerMode value";
1879 messages::internalError(aResp->res);
1880 return;
1881 }
1882
1883 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1884 {"Static", "MaximumPerformance", "PowerSaving"};
1885
1886 BMCWEB_LOG_DEBUG << "Current power mode: " << *s;
1887 translatePowerMode(aResp, *s);
1888 },
1889 service, path, "org.freedesktop.DBus.Properties", "Get",
1890 "xyz.openbmc_project.Control.Power.Mode", "PowerMode");
1891 },
1892 "xyz.openbmc_project.ObjectMapper",
1893 "/xyz/openbmc_project/object_mapper",
1894 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1895 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1896}
1897
1898/**
1899 * @brief Validate the specified mode is valid and return the PowerMode
1900 * name associated with that string
1901 *
1902 * @param[in] aResp Shared pointer for generating response message.
1903 * @param[in] modeString String representing the desired PowerMode
1904 *
1905 * @return PowerMode value or empty string if mode is not valid
1906 */
1907inline std::string
1908 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1909 const std::string& modeString)
1910{
1911 std::string mode;
1912
1913 if (modeString == "Static")
1914 {
1915 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
1916 }
1917 else if (modeString == "MaximumPerformance")
1918 {
1919 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode."
1920 "MaximumPerformance";
1921 }
1922 else if (modeString == "PowerSaving")
1923 {
1924 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
1925 }
1926 else
1927 {
1928 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
1929 }
1930 return mode;
1931}
1932
1933/**
1934 * @brief Sets system power mode.
1935 *
1936 * @param[in] aResp Shared pointer for generating response message.
1937 * @param[in] pmode System power mode from request.
1938 *
1939 * @return None.
1940 */
1941inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1942 const std::string& pmode)
1943{
1944 BMCWEB_LOG_DEBUG << "Set power mode.";
1945
1946 std::string powerMode = validatePowerMode(aResp, pmode);
1947 if (powerMode.empty())
1948 {
1949 return;
1950 }
1951
1952 // Get Power Mode object path:
1953 crow::connections::systemBus->async_method_call(
1954 [aResp, powerMode](
1955 const boost::system::error_code ec,
1956 const std::vector<std::pair<
1957 std::string,
1958 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1959 subtree) {
1960 if (ec)
1961 {
1962 BMCWEB_LOG_DEBUG
1963 << "DBUS response error on Power.Mode GetSubTree " << ec;
1964 // This is an optional D-Bus object, but user attempted to patch
1965 messages::internalError(aResp->res);
1966 return;
1967 }
1968 if (subtree.empty())
1969 {
1970 // This is an optional D-Bus object, but user attempted to patch
1971 messages::resourceNotFound(aResp->res, "ComputerSystem",
1972 "PowerMode");
1973 return;
1974 }
1975 if (subtree.size() > 1)
1976 {
1977 // More then one PowerMode object is not supported and is an
1978 // error
1979 BMCWEB_LOG_DEBUG
1980 << "Found more than 1 system D-Bus Power.Mode objects: "
1981 << subtree.size();
1982 messages::internalError(aResp->res);
1983 return;
1984 }
1985 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1986 {
1987 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1988 messages::internalError(aResp->res);
1989 return;
1990 }
1991 const std::string& path = subtree[0].first;
1992 const std::string& service = subtree[0].second.begin()->first;
1993 if (service.empty())
1994 {
1995 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1996 messages::internalError(aResp->res);
1997 return;
1998 }
1999
2000 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2001 << path;
2002
2003 // Set the Power Mode property
2004 crow::connections::systemBus->async_method_call(
2005 [aResp](const boost::system::error_code ec) {
2006 if (ec)
2007 {
2008 messages::internalError(aResp->res);
2009 return;
2010 }
2011 },
2012 service, path, "org.freedesktop.DBus.Properties", "Set",
2013 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2014 std::variant<std::string>(powerMode));
2015 },
2016 "xyz.openbmc_project.ObjectMapper",
2017 "/xyz/openbmc_project/object_mapper",
2018 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2019 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2020}
2021
2022/**
Yong Li51709ff2019-09-30 14:13:04 +08002023 * @brief Translates watchdog timeout action DBUS property value to redfish.
2024 *
2025 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2026 *
2027 * @return Returns as a string, the timeout action in Redfish terms. If
2028 * translation cannot be done, returns an empty string.
2029 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002030inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002031{
2032 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2033 {
2034 return "None";
2035 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002036 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002037 {
2038 return "ResetSystem";
2039 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002040 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002041 {
2042 return "PowerDown";
2043 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002044 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002045 {
2046 return "PowerCycle";
2047 }
2048
2049 return "";
2050}
2051
2052/**
Yong Lic45f0082019-10-10 14:19:01 +08002053 *@brief Translates timeout action from Redfish to DBUS property value.
2054 *
2055 *@param[in] rfAction The timeout action in Redfish.
2056 *
2057 *@return Returns as a string, the time_out action as expected by DBUS.
2058 *If translation cannot be done, returns an empty string.
2059 */
2060
Ed Tanous23a21a12020-07-25 04:45:05 +00002061inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002062{
2063 if (rfAction == "None")
2064 {
2065 return "xyz.openbmc_project.State.Watchdog.Action.None";
2066 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002067 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002068 {
2069 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2070 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002071 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002072 {
2073 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2074 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002075 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002076 {
2077 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2078 }
2079
2080 return "";
2081}
2082
2083/**
Yong Li51709ff2019-09-30 14:13:04 +08002084 * @brief Retrieves host watchdog timer properties over DBUS
2085 *
2086 * @param[in] aResp Shared pointer for completing asynchronous calls.
2087 *
2088 * @return None.
2089 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002090inline void
2091 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002092{
2093 BMCWEB_LOG_DEBUG << "Get host watchodg";
2094 crow::connections::systemBus->async_method_call(
2095 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002096 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002097 if (ec)
2098 {
2099 // watchdog service is stopped
2100 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2101 return;
2102 }
2103
2104 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2105
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002106 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002107 aResp->res.jsonValue["HostWatchdogTimer"];
2108
2109 // watchdog service is running/enabled
2110 hostWatchdogTimer["Status"]["State"] = "Enabled";
2111
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002112 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002113 {
2114 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2115 if (property.first == "Enabled")
2116 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002117 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002118
2119 if (!state)
2120 {
2121 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002122 return;
Yong Li51709ff2019-09-30 14:13:04 +08002123 }
2124
2125 hostWatchdogTimer["FunctionEnabled"] = *state;
2126 }
2127 else if (property.first == "ExpireAction")
2128 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002129 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002130 std::get_if<std::string>(&property.second);
2131 if (!s)
2132 {
2133 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002134 return;
Yong Li51709ff2019-09-30 14:13:04 +08002135 }
2136
2137 std::string action = dbusToRfWatchdogAction(*s);
2138 if (action.empty())
2139 {
2140 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002141 return;
Yong Li51709ff2019-09-30 14:13:04 +08002142 }
2143 hostWatchdogTimer["TimeoutAction"] = action;
2144 }
2145 }
2146 },
2147 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2148 "org.freedesktop.DBus.Properties", "GetAll",
2149 "xyz.openbmc_project.State.Watchdog");
2150}
2151
2152/**
Yong Lic45f0082019-10-10 14:19:01 +08002153 * @brief Sets Host WatchDog Timer properties.
2154 *
2155 * @param[in] aResp Shared pointer for generating response message.
2156 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2157 * RF request.
2158 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2159 *
2160 * @return None.
2161 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002162inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002163 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002164 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002165{
2166 BMCWEB_LOG_DEBUG << "Set host watchdog";
2167
2168 if (wdtTimeOutAction)
2169 {
2170 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2171 // check if TimeOut Action is Valid
2172 if (wdtTimeOutActStr.empty())
2173 {
2174 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2175 << *wdtTimeOutAction;
2176 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2177 "TimeoutAction");
2178 return;
2179 }
2180
2181 crow::connections::systemBus->async_method_call(
2182 [aResp](const boost::system::error_code ec) {
2183 if (ec)
2184 {
2185 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2186 messages::internalError(aResp->res);
2187 return;
2188 }
2189 },
2190 "xyz.openbmc_project.Watchdog",
2191 "/xyz/openbmc_project/watchdog/host0",
2192 "org.freedesktop.DBus.Properties", "Set",
2193 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
2194 std::variant<std::string>(wdtTimeOutActStr));
2195 }
2196
2197 if (wdtEnable)
2198 {
2199 crow::connections::systemBus->async_method_call(
2200 [aResp](const boost::system::error_code ec) {
2201 if (ec)
2202 {
2203 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2204 messages::internalError(aResp->res);
2205 return;
2206 }
2207 },
2208 "xyz.openbmc_project.Watchdog",
2209 "/xyz/openbmc_project/watchdog/host0",
2210 "org.freedesktop.DBus.Properties", "Set",
2211 "xyz.openbmc_project.State.Watchdog", "Enabled",
2212 std::variant<bool>(*wdtEnable));
2213 }
2214}
2215
2216/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002217 * SystemsCollection derived class for delivering ComputerSystems Collection
2218 * Schema
2219 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002220inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002221{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002222 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanous432a8902021-06-14 15:28:56 -07002223 .privileges({{"Login"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002224 .methods(boost::beast::http::verb::get)(
2225 [](const crow::Request& req,
2226 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2227 asyncResp->res.jsonValue["@odata.type"] =
2228 "#ComputerSystemCollection.ComputerSystemCollection";
2229 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2230 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002231
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002232 crow::connections::systemBus->async_method_call(
2233 [asyncResp,
2234 &req](const boost::system::error_code ec,
2235 const std::variant<std::string>& /*hostName*/) {
2236 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 */
2264void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2265{
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 Tanous432a8902021-06-14 15:28:56 -07002297 .privileges({{"ConfigureComponent"}})
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 Tanous432a8902021-06-14 15:28:56 -07002424 .privileges({{"Login"}})
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 Tanous432a8902021-06-14 15:28:56 -07002545 .privileges({{"ConfigureComponent"}})
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 Tanous432a8902021-06-14 15:28:56 -07002654 .privileges({{"Login"}})
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