blob: c1adc4c3ded8772460e29875613e24f5f6b5b836 [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
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070022#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080023#include "redfish_util.hpp"
24
John Edward Broadbent7e860f12021-04-08 15:57:16 -070025#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070026#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080027#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070028#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070029#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060030#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020031#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
Ed Tanousabf2add2019-01-22 16:40:12 -080033#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020034
Ed Tanous1abe55e2018-09-05 08:30:59 -070035namespace redfish
36{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020037
Alpana Kumari9d3ae102019-04-12 06:49:32 -050038/**
39 * @brief Updates the Functional State of DIMMs
40 *
41 * @param[in] aResp Shared pointer for completing asynchronous calls
42 * @param[in] dimmState Dimm's Functional state, true/false
43 *
44 * @return None.
45 */
zhanghch058d1b46d2021-04-01 11:18:24 +080046inline void
47 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070048 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070050 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050051
Gunnar Mills4e0453b2020-07-08 14:00:30 -050052 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050053 // Update STATE only if previous State was DISABLED and current Dimm is
54 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050055 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050056 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
57 if (prevMemSummary == "Disabled")
58 {
Ed Tanouse05aec52022-01-25 10:28:56 -080059 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050060 {
61 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
62 "Enabled";
63 }
64 }
65}
66
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050067/*
68 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
69 *
70 * @param[in] aResp Shared pointer for completing asynchronous calls
71 * @param[in] cpuPresenceState CPU present or not
72 *
73 * @return None.
74 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070075inline void
76 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
77 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050078{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070079 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050080
Ed Tanous55f79e62022-01-25 11:26:16 -080081 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050082 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050083 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080084 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080085 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050086 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080087 if (procCountPtr != nullptr)
88 {
89 // shouldn't be possible to be nullptr
90 *procCountPtr += 1;
91 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093}
94
95/*
96 * @brief Update "ProcessorSummary" "Status" "State" based on
97 * CPU Functional State
98 *
99 * @param[in] aResp Shared pointer for completing asynchronous calls
100 * @param[in] cpuFunctionalState is CPU functional true/false
101 *
102 * @return None.
103 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700104inline void
105 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
106 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500107{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700108 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500109
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500110 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500111 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
112
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500113 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114 // Update STATE only if previous State was Non_Functional and current CPU is
115 // Functional.
116 if (prevProcState == "Disabled")
117 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800118 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500119 {
120 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
121 "Enabled";
122 }
123 }
124}
125
Ed Tanousb9d36b42022-02-26 21:42:46 -0800126inline void
127 getProcessorProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
128 const std::string& service, const std::string& path,
129 const dbus::utility::DBusPropertiesMap& properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
Ed Tanouse662eae2022-01-25 10:39:19 -0800179 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500180 {
181 messages::internalError(aResp->res);
182 return;
183 }
184
185 nlohmann::json& coreCount =
186 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
187 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
188
189 if (coreCountPtr == nullptr)
190 {
191 coreCount = 0;
192 }
193 else
194 {
195 *coreCountPtr += *coreCountVal;
196 }
197 }
198 }
199}
200
201/*
202 * @brief Get ProcessorSummary fields
203 *
204 * @param[in] aResp Shared pointer for completing asynchronous calls
205 * @param[in] service dbus service for Cpu Information
206 * @param[in] path dbus path for Cpu
207 *
208 * @return None.
209 */
210inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 const std::string& service,
212 const std::string& path)
213{
214
215 crow::connections::systemBus->async_method_call(
216 [aResp, service,
217 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800218 const dbus::utility::DBusPropertiesMap& properties) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500219 if (ec2)
220 {
221 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
222 messages::internalError(aResp->res);
223 return;
224 }
225 getProcessorProperties(aResp, service, path, properties);
226 },
227 service, path, "org.freedesktop.DBus.Properties", "GetAll",
228 "xyz.openbmc_project.Inventory.Item.Cpu");
229}
230
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500231/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700232 * @brief Retrieves computer system properties over dbus
233 *
234 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500235 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700236 *
237 * @return None.
238 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700239inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800240 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700241 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700242{
Ed Tanous6c34de42018-08-29 13:37:36 -0700243 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500244
Ed Tanous6c34de42018-08-29 13:37:36 -0700245 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800246 [aResp,
247 systemHealth](const boost::system::error_code ec,
248 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700249 if (ec)
250 {
251 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700252 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700253 return;
254 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700255 // Iterate over all retrieved ObjectPaths.
256 for (const std::pair<std::string,
257 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500258 std::string, std::vector<std::string>>>>&
259 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700260 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500261 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700262 BMCWEB_LOG_DEBUG << "Got path: " << path;
263 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500264 std::pair<std::string, std::vector<std::string>>>&
265 connectionNames = object.second;
Ed Tanous26f69762022-01-25 09:49:11 -0800266 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700267 {
268 continue;
269 }
Ed Tanous029573d2019-02-01 10:57:49 -0800270
James Feist5bc2dc82019-10-22 14:33:16 -0700271 auto memoryHealth = std::make_shared<HealthPopulate>(
272 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
273
274 auto cpuHealth = std::make_shared<HealthPopulate>(
275 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
276
277 systemHealth->children.emplace_back(memoryHealth);
278 systemHealth->children.emplace_back(cpuHealth);
279
Ed Tanous029573d2019-02-01 10:57:49 -0800280 // This is not system, so check if it's cpu, dimm, UUID or
281 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500282 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700283 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500284 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700285 {
Ed Tanous029573d2019-02-01 10:57:49 -0800286 if (interfaceName ==
287 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700288 {
Ed Tanous029573d2019-02-01 10:57:49 -0800289 BMCWEB_LOG_DEBUG
290 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500291
Ed Tanous029573d2019-02-01 10:57:49 -0800292 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500293 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700294 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800295 const dbus::utility::DBusPropertiesMap&
Ed Tanousf23b7292020-10-15 09:41:17 -0700296 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000297 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800298 {
299 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000300 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800301 messages::internalError(aResp->res);
302 return;
303 }
304 BMCWEB_LOG_DEBUG << "Got "
305 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500306 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500307
Ed Tanous26f69762022-01-25 09:49:11 -0800308 if (!properties.empty())
Ed Tanous029573d2019-02-01 10:57:49 -0800309 {
Ed Tanous168e20c2021-12-13 14:39:53 -0800310 for (const std::pair<
311 std::string,
312 dbus::utility::
313 DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500314 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700315 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800316 if (property.first !=
317 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700318 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800319 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700320 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500321 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500322 std::get_if<uint32_t>(
323 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800324 if (value == nullptr)
325 {
326 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800327 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800328 continue;
329 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500330 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800331 aResp->res.jsonValue
332 ["MemorySummary"]
333 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500334 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800335 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500336 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800337 if (preValue == nullptr)
338 {
339 continue;
340 }
George Liu0fda0f12021-11-16 10:06:17 +0800341 aResp->res.jsonValue
342 ["MemorySummary"]
343 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800344 *value / (1024 * 1024) +
345 *preValue;
346 aResp->res
347 .jsonValue["MemorySummary"]
348 ["Status"]["State"] =
349 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700350 }
Ed Tanous029573d2019-02-01 10:57:49 -0800351 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500352 else
353 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700354 sdbusplus::asio::getProperty<bool>(
355 *crow::connections::systemBus,
356 service, path,
357 "xyz.openbmc_project.State."
358 "Decorator.OperationalStatus",
359 "Functional",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500360 [aResp](
361 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000362 ec3,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700363 bool dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000364 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500365 {
366 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800367 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000368 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500369 return;
370 }
371 updateDimmProperties(aResp,
372 dimmState);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700373 });
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500374 }
Ed Tanous029573d2019-02-01 10:57:49 -0800375 },
376 connection.first, path,
377 "org.freedesktop.DBus.Properties", "GetAll",
378 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700379
380 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800381 }
382 else if (interfaceName ==
383 "xyz.openbmc_project.Inventory.Item.Cpu")
384 {
385 BMCWEB_LOG_DEBUG
386 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500387
Ali Ahmed03fbed92021-09-03 02:33:43 -0500388 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700389
390 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800391 }
392 else if (interfaceName ==
393 "xyz.openbmc_project.Common.UUID")
394 {
395 BMCWEB_LOG_DEBUG
396 << "Found UUID, now get its properties.";
397 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800398 [aResp](const boost::system::error_code ec3,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800399 const dbus::utility::DBusPropertiesMap&
Ed Tanous168e20c2021-12-13 14:39:53 -0800400 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000401 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800402 {
403 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000404 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800405 messages::internalError(aResp->res);
406 return;
407 }
408 BMCWEB_LOG_DEBUG << "Got "
409 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500410 << " UUID properties.";
Ed Tanous168e20c2021-12-13 14:39:53 -0800411 for (const std::pair<
412 std::string,
413 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500414 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800415 {
Ed Tanous029573d2019-02-01 10:57:49 -0800416 if (property.first == "UUID")
417 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500418 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500419 std::get_if<std::string>(
420 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700421
Ed Tanous029573d2019-02-01 10:57:49 -0800422 if (value != nullptr)
423 {
424 std::string valueStr = *value;
425 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700426 {
Ed Tanous029573d2019-02-01 10:57:49 -0800427 valueStr.insert(8, 1, '-');
428 valueStr.insert(13, 1, '-');
429 valueStr.insert(18, 1, '-');
430 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700431 }
Ed Tanous029573d2019-02-01 10:57:49 -0800432 BMCWEB_LOG_DEBUG << "UUID = "
433 << valueStr;
434 aResp->res.jsonValue["UUID"] =
435 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700436 }
437 }
Ed Tanous029573d2019-02-01 10:57:49 -0800438 }
439 },
440 connection.first, path,
441 "org.freedesktop.DBus.Properties", "GetAll",
442 "xyz.openbmc_project.Common.UUID");
443 }
444 else if (interfaceName ==
445 "xyz.openbmc_project.Inventory.Item.System")
446 {
447 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800448 [aResp](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800449 const dbus::utility::DBusPropertiesMap&
Ed Tanous168e20c2021-12-13 14:39:53 -0800450 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000451 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800452 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700453 // doesn't have to include this
454 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800455 return;
456 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500457 BMCWEB_LOG_DEBUG
458 << "Got " << propertiesList.size()
459 << " properties for system";
Ed Tanous168e20c2021-12-13 14:39:53 -0800460 for (const std::pair<
461 std::string,
462 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500463 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800464 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500465 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600466 property.first;
467 if ((propertyName == "PartNumber") ||
468 (propertyName == "SerialNumber") ||
469 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500470 (propertyName == "Model") ||
471 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800472 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500473 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600474 std::get_if<std::string>(
475 &property.second);
476 if (value != nullptr)
477 {
478 aResp->res
479 .jsonValue[propertyName] =
480 *value;
481 }
Ed Tanous029573d2019-02-01 10:57:49 -0800482 }
483 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500484
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600485 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500486 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600487 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500488 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800489 },
490 connection.first, path,
491 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800492 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700493
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700494 sdbusplus::asio::getProperty<std::string>(
495 *crow::connections::systemBus, connection.first,
496 path,
497 "xyz.openbmc_project.Inventory.Decorator."
498 "AssetTag",
499 "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -0800500 [aResp](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700501 const std::string& value) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000502 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700503 {
504 // doesn't have to include this
505 // interface
506 return;
507 }
508
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700509 aResp->res.jsonValue["AssetTag"] = value;
510 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700511 }
512 }
513 }
514 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700515 },
516 "xyz.openbmc_project.ObjectMapper",
517 "/xyz/openbmc_project/object_mapper",
518 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700519 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500520 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700521 "xyz.openbmc_project.Inventory.Decorator.Asset",
522 "xyz.openbmc_project.Inventory.Item.Cpu",
523 "xyz.openbmc_project.Inventory.Item.Dimm",
524 "xyz.openbmc_project.Inventory.Item.System",
525 "xyz.openbmc_project.Common.UUID",
526 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700527}
528
529/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700530 * @brief Retrieves host state properties over dbus
531 *
532 * @param[in] aResp Shared pointer for completing asynchronous calls.
533 *
534 * @return None.
535 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800536inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700537{
538 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700539 sdbusplus::asio::getProperty<std::string>(
540 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
541 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
542 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800543 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700544 const std::string& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700545 if (ec)
546 {
Andrew Geissler22228c22022-01-31 13:55:33 -0600547 if (ec == boost::system::errc::host_unreachable)
548 {
549 // Service not available, no error, just don't return
550 // host state info
551 BMCWEB_LOG_DEBUG << "Service not available " << ec;
552 return;
553 }
554 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700555 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700556 return;
557 }
Ed Tanous66173382018-08-15 18:20:59 -0700558
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700559 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
560 // Verify Host State
561 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700562 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700563 aResp->res.jsonValue["PowerState"] = "On";
564 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700565 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700566 else if (hostState ==
567 "xyz.openbmc_project.State.Host.HostState.Quiesced")
568 {
569 aResp->res.jsonValue["PowerState"] = "On";
570 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
571 }
572 else if (hostState ==
573 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
574 {
575 aResp->res.jsonValue["PowerState"] = "On";
576 aResp->res.jsonValue["Status"]["State"] = "InTest";
577 }
578 else if (
579 hostState ==
580 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
581 {
582 aResp->res.jsonValue["PowerState"] = "PoweringOn";
583 aResp->res.jsonValue["Status"]["State"] = "Starting";
584 }
585 else if (
586 hostState ==
587 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
588 {
589 aResp->res.jsonValue["PowerState"] = "PoweringOff";
590 aResp->res.jsonValue["Status"]["State"] = "Disabled";
591 }
592 else
593 {
594 aResp->res.jsonValue["PowerState"] = "Off";
595 aResp->res.jsonValue["Status"]["State"] = "Disabled";
596 }
597 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700598}
599
600/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500601 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530602 *
603 * @param[in] dbusSource The boot source in DBUS speak.
604 *
605 * @return Returns as a string, the boot source in Redfish terms. If translation
606 * cannot be done, returns an empty string.
607 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000608inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530609{
610 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
611 {
612 return "None";
613 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700614 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615 {
616 return "Hdd";
617 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700618 if (dbusSource ==
619 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530620 {
621 return "Cd";
622 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700623 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530624 {
625 return "Pxe";
626 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700627 if (dbusSource ==
628 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700629 {
630 return "Usb";
631 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700632 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530633}
634
635/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300636 * @brief Translates boot type DBUS property value to redfish.
637 *
638 * @param[in] dbusType The boot type in DBUS speak.
639 *
640 * @return Returns as a string, the boot type in Redfish terms. If translation
641 * cannot be done, returns an empty string.
642 */
643inline std::string dbusToRfBootType(const std::string& dbusType)
644{
645 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
646 {
647 return "Legacy";
648 }
649 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
650 {
651 return "UEFI";
652 }
653 return "";
654}
655
656/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500657 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530658 *
659 * @param[in] dbusMode The boot mode in DBUS speak.
660 *
661 * @return Returns as a string, the boot mode in Redfish terms. If translation
662 * cannot be done, returns an empty string.
663 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000664inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530665{
666 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
667 {
668 return "None";
669 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700670 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530671 {
672 return "Diags";
673 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700674 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530675 {
676 return "BiosSetup";
677 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700678 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530679}
680
681/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600682 * @brief Translates boot progress DBUS property value to redfish.
683 *
684 * @param[in] dbusBootProgress The boot progress in DBUS speak.
685 *
686 * @return Returns as a string, the boot progress in Redfish terms. If
687 * translation cannot be done, returns "None".
688 */
689inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
690{
691 // Now convert the D-Bus BootProgress to the appropriate Redfish
692 // enum
693 std::string rfBpLastState = "None";
694 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
695 "ProgressStages.Unspecified")
696 {
697 rfBpLastState = "None";
698 }
699 else if (dbusBootProgress ==
700 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
701 "PrimaryProcInit")
702 {
703 rfBpLastState = "PrimaryProcessorInitializationStarted";
704 }
705 else if (dbusBootProgress ==
706 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
707 "BusInit")
708 {
709 rfBpLastState = "BusInitializationStarted";
710 }
711 else if (dbusBootProgress ==
712 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
713 "MemoryInit")
714 {
715 rfBpLastState = "MemoryInitializationStarted";
716 }
717 else if (dbusBootProgress ==
718 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
719 "SecondaryProcInit")
720 {
721 rfBpLastState = "SecondaryProcessorInitializationStarted";
722 }
723 else if (dbusBootProgress ==
724 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
725 "PCIInit")
726 {
727 rfBpLastState = "PCIResourceConfigStarted";
728 }
729 else if (dbusBootProgress ==
730 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
731 "SystemSetup")
732 {
733 rfBpLastState = "SetupEntered";
734 }
735 else if (dbusBootProgress ==
736 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
737 "SystemInitComplete")
738 {
739 rfBpLastState = "SystemHardwareInitializationComplete";
740 }
741 else if (dbusBootProgress ==
742 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
743 "OSStart")
744 {
745 rfBpLastState = "OSBootStarted";
746 }
747 else if (dbusBootProgress ==
748 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
749 "OSRunning")
750 {
751 rfBpLastState = "OSRunning";
752 }
753 else
754 {
755 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
756 << dbusBootProgress;
757 // Just return the default
758 }
759 return rfBpLastState;
760}
761
762/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500763 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530764 *
765 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 * @param[out] bootSource The DBus source
767 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530768 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700769 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530770 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800771inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500772 const std::string& rfSource,
773 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300775 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
776 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700777
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 if (rfSource == "None")
779 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700782 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530783 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700784 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
785 }
786 else if (rfSource == "Hdd")
787 {
788 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
789 }
790 else if (rfSource == "Diags")
791 {
792 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
793 }
794 else if (rfSource == "Cd")
795 {
796 bootSource =
797 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
798 }
799 else if (rfSource == "BiosSetup")
800 {
801 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530802 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700803 else if (rfSource == "Usb")
804 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700805 bootSource =
806 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700807 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530808 else
809 {
George Liu0fda0f12021-11-16 10:06:17 +0800810 BMCWEB_LOG_DEBUG
811 << "Invalid property value for BootSourceOverrideTarget: "
812 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700813 messages::propertyValueNotInList(aResp->res, rfSource,
814 "BootSourceTargetOverride");
815 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530816 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700817 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818}
Ali Ahmed19817712021-06-29 17:01:52 -0500819
Andrew Geissler978b8802020-11-19 13:36:40 -0600820/**
821 * @brief Retrieves boot progress of the system
822 *
823 * @param[in] aResp Shared pointer for generating response message.
824 *
825 * @return None.
826 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800827inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600828{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700829 sdbusplus::asio::getProperty<std::string>(
830 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
831 "/xyz/openbmc_project/state/host0",
832 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600833 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700834 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600835 if (ec)
836 {
837 // BootProgress is an optional object so just do nothing if
838 // not found
839 return;
840 }
841
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700842 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600843
Andrew Geisslere43914b2022-01-06 13:59:39 -0600844 aResp->res.jsonValue["BootProgress"]["LastState"] =
845 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700846 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600847}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530848
849/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300850 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300851 *
852 * @param[in] aResp Shared pointer for generating response message.
853 *
854 * @return None.
855 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300856
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300857inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300858{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700859 sdbusplus::asio::getProperty<std::string>(
860 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
861 "/xyz/openbmc_project/control/host0/boot",
862 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300863 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700864 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300865 if (ec)
866 {
867 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868 return;
869 }
870
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700871 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300872
George Liu0fda0f12021-11-16 10:06:17 +0800873 aResp->res
874 .jsonValue["Boot"]
875 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
876 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300877
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700878 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300879 if (rfType.empty())
880 {
881 messages::internalError(aResp->res);
882 return;
883 }
884
885 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700886 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300887}
888
889/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300890 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530891 *
892 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530893 *
894 * @return None.
895 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300896
897inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530898{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700899 sdbusplus::asio::getProperty<std::string>(
900 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
901 "/xyz/openbmc_project/control/host0/boot",
902 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300903 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700904 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530905 if (ec)
906 {
907 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
908 messages::internalError(aResp->res);
909 return;
910 }
911
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700912 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530913
George Liu0fda0f12021-11-16 10:06:17 +0800914 aResp->res
915 .jsonValue["Boot"]
916 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
917 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530918
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700919 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530920 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
921 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700922 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923 if (!rfMode.empty())
924 {
925 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
926 rfMode;
927 }
928 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700929 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530930}
931
932/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300933 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530934 *
935 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530936 *
937 * @return None.
938 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300939
940inline void
941 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530942{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700943 sdbusplus::asio::getProperty<std::string>(
944 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
945 "/xyz/openbmc_project/control/host0/boot",
946 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300947 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700948 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530949 if (ec)
950 {
951 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
952 messages::internalError(aResp->res);
953 return;
954 }
955
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700956 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530957
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700958 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 if (!rfSource.empty())
960 {
961 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
962 rfSource;
963 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300964
965 // Get BootMode as BootSourceOverrideTarget is constructed
966 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300967 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700968 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969}
970
971/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300972 * @brief This functions abstracts all the logic behind getting a
973 * "BootSourceOverrideEnabled" property from an overall boot override enable
974 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530975 *
976 * @param[in] aResp Shared pointer for generating response message.
977 *
978 * @return None.
979 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530980
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300981inline void
982 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
983 const bool bootOverrideEnableSetting)
984{
985 if (!bootOverrideEnableSetting)
986 {
987 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
988 return;
989 }
990
991 // If boot source override is enabled, we need to check 'one_time'
992 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700993 sdbusplus::asio::getProperty<bool>(
994 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
995 "/xyz/openbmc_project/control/host0/boot/one_time",
996 "xyz.openbmc_project.Object.Enable", "Enabled",
997 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530998 if (ec)
999 {
1000 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001001 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301002 return;
1003 }
1004
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001005 if (oneTimeSetting)
1006 {
1007 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1008 "Once";
1009 }
1010 else
1011 {
1012 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1013 "Continuous";
1014 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001015 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301016}
1017
1018/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001019 * @brief Retrieves boot override enable over DBUS
1020 *
1021 * @param[in] aResp Shared pointer for generating response message.
1022 *
1023 * @return None.
1024 */
1025
1026inline void
1027 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1028{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001029 sdbusplus::asio::getProperty<bool>(
1030 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1031 "/xyz/openbmc_project/control/host0/boot",
1032 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001033 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001034 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001035 if (ec)
1036 {
1037 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1038 messages::internalError(aResp->res);
1039 return;
1040 }
1041
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001042 processBootOverrideEnable(aResp, bootOverrideEnable);
1043 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001044}
1045
1046/**
1047 * @brief Retrieves boot source override properties
1048 *
1049 * @param[in] aResp Shared pointer for generating response message.
1050 *
1051 * @return None.
1052 */
1053inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1054{
1055 BMCWEB_LOG_DEBUG << "Get boot information.";
1056
1057 getBootOverrideSource(aResp);
1058 getBootOverrideType(aResp);
1059 getBootOverrideEnable(aResp);
1060}
1061
1062/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001063 * @brief Retrieves the Last Reset Time
1064 *
1065 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1066 * and power off. Even though this is the "system" Redfish object look at the
1067 * chassis D-Bus interface for the LastStateChangeTime since this has the
1068 * last power operation time.
1069 *
1070 * @param[in] aResp Shared pointer for generating response message.
1071 *
1072 * @return None.
1073 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001074inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001075{
1076 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1077
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001078 sdbusplus::asio::getProperty<uint64_t>(
1079 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1080 "/xyz/openbmc_project/state/chassis0",
1081 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1082 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001083 if (ec)
1084 {
1085 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1086 return;
1087 }
1088
Gunnar Millsc0557e12020-06-30 11:26:20 -05001089 // LastStateChangeTime is epoch time, in milliseconds
1090 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001091 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001092
1093 // Convert to ISO 8601 standard
1094 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001095 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001096 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001097}
1098
1099/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001100 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1101 *
1102 * @param[in] aResp Shared pointer for generating response message.
1103 *
1104 * @return None.
1105 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001106inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001107{
1108 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1109
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001110 sdbusplus::asio::getProperty<bool>(
1111 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1112 "/xyz/openbmc_project/control/host0/auto_reboot",
1113 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1114 [aResp](const boost::system::error_code ec, 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
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001121 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
Ed Tanouse05aec52022-01-25 10:28:56 -08001122 if (autoRebootEnabled)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001123 {
1124 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1125 "RetryAttempts";
1126 // If AutomaticRetry (AutoReboot) is enabled see how many
1127 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001128 sdbusplus::asio::getProperty<uint32_t>(
1129 *crow::connections::systemBus,
1130 "xyz.openbmc_project.State.Host",
1131 "/xyz/openbmc_project/state/host0",
1132 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1133 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001134 [aResp](const boost::system::error_code ec2,
Ed Tanous914e2d52022-01-07 11:38:34 -08001135 const uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001136 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001137 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001138 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001139 return;
1140 }
1141
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001142 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001143 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001144
1145 aResp->res
1146 .jsonValue["Boot"]
1147 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001148 autoRebootAttemptsLeft;
1149 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001150 }
1151 else
1152 {
1153 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1154 "Disabled";
1155 }
1156
1157 // Not on D-Bus. Hardcoded here:
1158 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1159 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001160
1161 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1162 // and RetryAttempts. OpenBMC only supports Disabled and
1163 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001164 aResp->res
1165 .jsonValue["Boot"]
1166 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1167 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001168 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001169}
1170
1171/**
George Liuc6a620f2020-04-10 17:18:11 +08001172 * @brief Retrieves power restore policy over DBUS.
1173 *
1174 * @param[in] aResp Shared pointer for generating response message.
1175 *
1176 * @return None.
1177 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001178inline void
1179 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001180{
1181 BMCWEB_LOG_DEBUG << "Get power restore policy";
1182
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001183 sdbusplus::asio::getProperty<std::string>(
1184 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1185 "/xyz/openbmc_project/control/host0/power_restore_policy",
1186 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1187 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001188 if (ec)
1189 {
1190 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1191 return;
1192 }
1193
George Liu0fda0f12021-11-16 10:06:17 +08001194 const boost::container::flat_map<std::string, std::string> policyMaps = {
1195 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1196 "AlwaysOn"},
1197 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1198 "AlwaysOff"},
1199 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
Matthew Barth4ed47cb2022-03-03 15:58:06 -06001200 "LastState"},
1201 // Return `AlwaysOff` when power restore policy set to "None"
1202 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1203 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001204
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001205 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001206 if (policyMapsIt == policyMaps.end())
1207 {
1208 messages::internalError(aResp->res);
1209 return;
1210 }
1211
1212 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001213 });
George Liuc6a620f2020-04-10 17:18:11 +08001214}
1215
1216/**
Ali Ahmed19817712021-06-29 17:01:52 -05001217 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1218 * TPM is required for booting the host.
1219 *
1220 * @param[in] aResp Shared pointer for generating response message.
1221 *
1222 * @return None.
1223 */
1224inline void getTrustedModuleRequiredToBoot(
1225 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1226{
1227 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1228
1229 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001230 [aResp](const boost::system::error_code ec,
1231 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ali Ahmed19817712021-06-29 17:01:52 -05001232 if (ec)
1233 {
1234 BMCWEB_LOG_DEBUG
1235 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1236 // This is an optional D-Bus object so just return if
1237 // error occurs
1238 return;
1239 }
Ed Tanous26f69762022-01-25 09:49:11 -08001240 if (subtree.empty())
Ali Ahmed19817712021-06-29 17:01:52 -05001241 {
1242 // As noted above, this is an optional interface so just return
1243 // if there is no instance found
1244 return;
1245 }
1246
1247 /* When there is more than one TPMEnable object... */
1248 if (subtree.size() > 1)
1249 {
1250 BMCWEB_LOG_DEBUG
1251 << "DBUS response has more than 1 TPM Enable object:"
1252 << subtree.size();
1253 // Throw an internal Error and return
1254 messages::internalError(aResp->res);
1255 return;
1256 }
1257
1258 // Make sure the Dbus response map has a service and objectPath
1259 // field
1260 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1261 {
1262 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1263 messages::internalError(aResp->res);
1264 return;
1265 }
1266
1267 const std::string& path = subtree[0].first;
1268 const std::string& serv = subtree[0].second.begin()->first;
1269
1270 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001271 sdbusplus::asio::getProperty<bool>(
1272 *crow::connections::systemBus, serv, path,
1273 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1274 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001275 if (ec)
1276 {
1277 BMCWEB_LOG_DEBUG
1278 << "D-BUS response error on TPM.Policy Get" << ec;
1279 messages::internalError(aResp->res);
1280 return;
1281 }
1282
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001283 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001284 {
1285 aResp->res
1286 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1287 "Required";
1288 }
1289 else
1290 {
1291 aResp->res
1292 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1293 "Disabled";
1294 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001295 });
Ali Ahmed19817712021-06-29 17:01:52 -05001296 },
1297 "xyz.openbmc_project.ObjectMapper",
1298 "/xyz/openbmc_project/object_mapper",
1299 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1300 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1301}
1302
1303/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001304 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1305 * TPM is required for booting the host.
1306 *
1307 * @param[in] aResp Shared pointer for generating response message.
1308 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1309 *
1310 * @return None.
1311 */
1312inline void setTrustedModuleRequiredToBoot(
1313 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1314{
1315 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1316
1317 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001318 [aResp, tpmRequired](const boost::system::error_code ec,
1319 dbus::utility::MapperGetSubTreeResponse& subtree) {
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001320 if (ec)
1321 {
1322 BMCWEB_LOG_DEBUG
1323 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1324 messages::internalError(aResp->res);
1325 return;
1326 }
Ed Tanous26f69762022-01-25 09:49:11 -08001327 if (subtree.empty())
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001328 {
1329 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1330 "TrustedModuleRequiredToBoot");
1331 return;
1332 }
1333
1334 /* When there is more than one TPMEnable object... */
1335 if (subtree.size() > 1)
1336 {
1337 BMCWEB_LOG_DEBUG
1338 << "DBUS response has more than 1 TPM Enable object:"
1339 << subtree.size();
1340 // Throw an internal Error and return
1341 messages::internalError(aResp->res);
1342 return;
1343 }
1344
1345 // Make sure the Dbus response map has a service and objectPath
1346 // field
1347 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1348 {
1349 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1350 messages::internalError(aResp->res);
1351 return;
1352 }
1353
1354 const std::string& path = subtree[0].first;
1355 const std::string& serv = subtree[0].second.begin()->first;
1356
1357 if (serv.empty())
1358 {
1359 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1360 messages::internalError(aResp->res);
1361 return;
1362 }
1363
1364 // Valid TPM Enable object found, now setting the value
1365 crow::connections::systemBus->async_method_call(
1366 [aResp](const boost::system::error_code ec) {
1367 if (ec)
1368 {
George Liu0fda0f12021-11-16 10:06:17 +08001369 BMCWEB_LOG_DEBUG
1370 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1371 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001372 messages::internalError(aResp->res);
1373 return;
1374 }
1375 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1376 },
1377 serv, path, "org.freedesktop.DBus.Properties", "Set",
1378 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001379 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001380 },
1381 "xyz.openbmc_project.ObjectMapper",
1382 "/xyz/openbmc_project/object_mapper",
1383 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1384 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1385}
1386
1387/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301388 * @brief Sets boot properties into DBUS object(s).
1389 *
1390 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001391 * @param[in] bootType The boot type to set.
1392 * @return Integer error code.
1393 */
1394inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001395 const std::optional<std::string>& bootType)
1396{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001397 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001398
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001399 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001400 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001401 return;
1402 }
1403
1404 // Source target specified
1405 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1406 // Figure out which DBUS interface and property to use
1407 if (*bootType == "Legacy")
1408 {
1409 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1410 }
1411 else if (*bootType == "UEFI")
1412 {
1413 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1414 }
1415 else
1416 {
1417 BMCWEB_LOG_DEBUG << "Invalid property value for "
1418 "BootSourceOverrideMode: "
1419 << *bootType;
1420 messages::propertyValueNotInList(aResp->res, *bootType,
1421 "BootSourceOverrideMode");
1422 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001423 }
1424
1425 // Act on validated parameters
1426 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1427
1428 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001429 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001430 if (ec)
1431 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001432 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1433 if (ec.value() == boost::asio::error::host_unreachable)
1434 {
1435 messages::resourceNotFound(aResp->res, "Set", "BootType");
1436 return;
1437 }
1438 messages::internalError(aResp->res);
1439 return;
1440 }
1441 BMCWEB_LOG_DEBUG << "Boot type update done.";
1442 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001443 "xyz.openbmc_project.Settings",
1444 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001445 "org.freedesktop.DBus.Properties", "Set",
1446 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001447 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001448}
1449
1450/**
1451 * @brief Sets boot properties into DBUS object(s).
1452 *
1453 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001454 * @param[in] bootType The boot type to set.
1455 * @return Integer error code.
1456 */
1457inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1458 const std::optional<std::string>& bootEnable)
1459{
1460 if (!bootEnable)
1461 {
1462 return;
1463 }
1464 // Source target specified
1465 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1466
1467 bool bootOverrideEnable = false;
1468 bool bootOverridePersistent = false;
1469 // Figure out which DBUS interface and property to use
1470 if (*bootEnable == "Disabled")
1471 {
1472 bootOverrideEnable = false;
1473 }
1474 else if (*bootEnable == "Once")
1475 {
1476 bootOverrideEnable = true;
1477 bootOverridePersistent = false;
1478 }
1479 else if (*bootEnable == "Continuous")
1480 {
1481 bootOverrideEnable = true;
1482 bootOverridePersistent = true;
1483 }
1484 else
1485 {
George Liu0fda0f12021-11-16 10:06:17 +08001486 BMCWEB_LOG_DEBUG
1487 << "Invalid property value for BootSourceOverrideEnabled: "
1488 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001489 messages::propertyValueNotInList(aResp->res, *bootEnable,
1490 "BootSourceOverrideEnabled");
1491 return;
1492 }
1493
1494 // Act on validated parameters
1495 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1496
1497 crow::connections::systemBus->async_method_call(
1498 [aResp](const boost::system::error_code ec) {
1499 if (ec)
1500 {
1501 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1502 messages::internalError(aResp->res);
1503 return;
1504 }
1505 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1506 },
1507 "xyz.openbmc_project.Settings",
1508 "/xyz/openbmc_project/control/host0/boot",
1509 "org.freedesktop.DBus.Properties", "Set",
1510 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001511 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001512
1513 if (!bootOverrideEnable)
1514 {
1515 return;
1516 }
1517
1518 // In case boot override is enabled we need to set correct value for the
1519 // 'one_time' enable DBus interface
1520 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1521 << bootOverridePersistent;
1522
1523 crow::connections::systemBus->async_method_call(
1524 [aResp](const boost::system::error_code ec) {
1525 if (ec)
1526 {
1527 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1528 messages::internalError(aResp->res);
1529 return;
1530 }
1531 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1532 },
1533 "xyz.openbmc_project.Settings",
1534 "/xyz/openbmc_project/control/host0/boot/one_time",
1535 "org.freedesktop.DBus.Properties", "Set",
1536 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001537 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001538}
1539
1540/**
1541 * @brief Sets boot properties into DBUS object(s).
1542 *
1543 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301544 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301545 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001546 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301547 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001548inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001549 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301550{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001551 std::string bootSourceStr;
1552 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001553
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001554 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301555 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001556 return;
1557 }
1558
1559 // Source target specified
1560 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1561 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001562 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1563 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001564 {
1565 BMCWEB_LOG_DEBUG
1566 << "Invalid property value for BootSourceOverrideTarget: "
1567 << *bootSource;
1568 messages::propertyValueNotInList(aResp->res, *bootSource,
1569 "BootSourceTargetOverride");
1570 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001571 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301572
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001573 // Act on validated parameters
1574 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1575 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001576
1577 crow::connections::systemBus->async_method_call(
1578 [aResp](const boost::system::error_code ec) {
1579 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301580 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001581 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1582 messages::internalError(aResp->res);
1583 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301584 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001585 BMCWEB_LOG_DEBUG << "Boot source update done.";
1586 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001587 "xyz.openbmc_project.Settings",
1588 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001589 "org.freedesktop.DBus.Properties", "Set",
1590 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001591 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001592
1593 crow::connections::systemBus->async_method_call(
1594 [aResp](const boost::system::error_code ec) {
1595 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301596 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001597 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1598 messages::internalError(aResp->res);
1599 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301600 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001601 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1602 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001603 "xyz.openbmc_project.Settings",
1604 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001605 "org.freedesktop.DBus.Properties", "Set",
1606 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001607 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001608}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001609
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001610/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001611 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301612 *
1613 * @param[in] aResp Shared pointer for generating response message.
1614 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001615 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301616 * @param[in] bootEnable The boot override enable from incoming RF request.
1617 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001618 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301619 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001620
1621inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1622 const std::optional<std::string>& bootSource,
1623 const std::optional<std::string>& bootType,
1624 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301625{
1626 BMCWEB_LOG_DEBUG << "Set boot information.";
1627
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001628 setBootModeOrSource(aResp, bootSource);
1629 setBootType(aResp, bootType);
1630 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301631}
1632
George Liuc6a620f2020-04-10 17:18:11 +08001633/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001634 * @brief Sets AssetTag
1635 *
1636 * @param[in] aResp Shared pointer for generating response message.
1637 * @param[in] assetTag "AssetTag" from request.
1638 *
1639 * @return None.
1640 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001641inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001642 const std::string& assetTag)
1643{
1644 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001645 [aResp,
1646 assetTag](const boost::system::error_code ec,
1647 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Gunnar Mills98e386e2020-10-30 14:58:09 -05001648 if (ec)
1649 {
1650 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1651 messages::internalError(aResp->res);
1652 return;
1653 }
Ed Tanous26f69762022-01-25 09:49:11 -08001654 if (subtree.empty())
Gunnar Mills98e386e2020-10-30 14:58:09 -05001655 {
1656 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1657 messages::internalError(aResp->res);
1658 return;
1659 }
1660 // Assume only 1 system D-Bus object
1661 // Throw an error if there is more than 1
1662 if (subtree.size() > 1)
1663 {
1664 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1665 messages::internalError(aResp->res);
1666 return;
1667 }
1668 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1669 {
1670 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1671 messages::internalError(aResp->res);
1672 return;
1673 }
1674
1675 const std::string& path = subtree[0].first;
1676 const std::string& service = subtree[0].second.begin()->first;
1677
1678 if (service.empty())
1679 {
1680 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1681 messages::internalError(aResp->res);
1682 return;
1683 }
1684
1685 crow::connections::systemBus->async_method_call(
1686 [aResp](const boost::system::error_code ec2) {
1687 if (ec2)
1688 {
1689 BMCWEB_LOG_DEBUG
1690 << "D-Bus response error on AssetTag Set " << ec2;
1691 messages::internalError(aResp->res);
1692 return;
1693 }
1694 },
1695 service, path, "org.freedesktop.DBus.Properties", "Set",
1696 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001697 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001698 },
1699 "xyz.openbmc_project.ObjectMapper",
1700 "/xyz/openbmc_project/object_mapper",
1701 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1702 "/xyz/openbmc_project/inventory", int32_t(0),
1703 std::array<const char*, 1>{
1704 "xyz.openbmc_project.Inventory.Item.System"});
1705}
1706
1707/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001708 * @brief Sets automaticRetry (Auto Reboot)
1709 *
1710 * @param[in] aResp Shared pointer for generating response message.
1711 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1712 *
1713 * @return None.
1714 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001715inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001716 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001717{
1718 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1719
1720 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001721 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001722
1723 if (automaticRetryConfig == "Disabled")
1724 {
1725 autoRebootEnabled = false;
1726 }
1727 else if (automaticRetryConfig == "RetryAttempts")
1728 {
1729 autoRebootEnabled = true;
1730 }
1731 else
1732 {
George Liu0fda0f12021-11-16 10:06:17 +08001733 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001734 << automaticRetryConfig;
1735 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1736 "AutomaticRetryConfig");
1737 return;
1738 }
1739
1740 crow::connections::systemBus->async_method_call(
1741 [aResp](const boost::system::error_code ec) {
1742 if (ec)
1743 {
1744 messages::internalError(aResp->res);
1745 return;
1746 }
1747 },
1748 "xyz.openbmc_project.Settings",
1749 "/xyz/openbmc_project/control/host0/auto_reboot",
1750 "org.freedesktop.DBus.Properties", "Set",
1751 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001752 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001753}
1754
1755/**
George Liuc6a620f2020-04-10 17:18:11 +08001756 * @brief Sets power restore policy properties.
1757 *
1758 * @param[in] aResp Shared pointer for generating response message.
1759 * @param[in] policy power restore policy properties from request.
1760 *
1761 * @return None.
1762 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001763inline void
1764 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1765 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001766{
1767 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1768
1769 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001770 {"AlwaysOn",
1771 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1772 {"AlwaysOff",
1773 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1774 {"LastState",
1775 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001776
1777 std::string powerRestorPolicy;
1778
Gunnar Mills4e69c902021-01-05 19:50:11 -06001779 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001780 if (policyMapsIt == policyMaps.end())
1781 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001782 messages::propertyValueNotInList(aResp->res, policy,
1783 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001784 return;
1785 }
1786
1787 powerRestorPolicy = policyMapsIt->second;
1788
1789 crow::connections::systemBus->async_method_call(
1790 [aResp](const boost::system::error_code ec) {
1791 if (ec)
1792 {
1793 messages::internalError(aResp->res);
1794 return;
1795 }
1796 },
1797 "xyz.openbmc_project.Settings",
1798 "/xyz/openbmc_project/control/host0/power_restore_policy",
1799 "org.freedesktop.DBus.Properties", "Set",
1800 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001801 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001802}
1803
AppaRao Pulia6349912019-10-18 17:16:08 +05301804#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1805/**
1806 * @brief Retrieves provisioning status
1807 *
1808 * @param[in] aResp Shared pointer for completing asynchronous calls.
1809 *
1810 * @return None.
1811 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001812inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301813{
1814 BMCWEB_LOG_DEBUG << "Get OEM information.";
1815 crow::connections::systemBus->async_method_call(
1816 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001817 const dbus::utility::DBusPropertiesMap& propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301818 nlohmann::json& oemPFR =
1819 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001820 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1821 "#OemComputerSystem.OpenBmc";
1822 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1823
AppaRao Pulia6349912019-10-18 17:16:08 +05301824 if (ec)
1825 {
1826 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301827 // not an error, don't have to have the interface
1828 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301829 return;
1830 }
1831
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001832 const bool* provState = nullptr;
1833 const bool* lockState = nullptr;
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001834 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1835 property : propertiesList)
AppaRao Pulia6349912019-10-18 17:16:08 +05301836 {
1837 if (property.first == "UfmProvisioned")
1838 {
1839 provState = std::get_if<bool>(&property.second);
1840 }
1841 else if (property.first == "UfmLocked")
1842 {
1843 lockState = std::get_if<bool>(&property.second);
1844 }
1845 }
1846
1847 if ((provState == nullptr) || (lockState == nullptr))
1848 {
1849 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1850 messages::internalError(aResp->res);
1851 return;
1852 }
1853
AppaRao Pulia6349912019-10-18 17:16:08 +05301854 if (*provState == true)
1855 {
1856 if (*lockState == true)
1857 {
1858 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1859 }
1860 else
1861 {
1862 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1863 }
1864 }
1865 else
1866 {
1867 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1868 }
1869 },
1870 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1871 "org.freedesktop.DBus.Properties", "GetAll",
1872 "xyz.openbmc_project.PFR.Attributes");
1873}
1874#endif
1875
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301876/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001877 * @brief Translate the PowerMode to a response message.
1878 *
1879 * @param[in] aResp Shared pointer for generating response message.
1880 * @param[in] modeValue PowerMode value to be translated
1881 *
1882 * @return None.
1883 */
1884inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1885 const std::string& modeValue)
1886{
George Liu0fda0f12021-11-16 10:06:17 +08001887 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001888 {
1889 aResp->res.jsonValue["PowerMode"] = "Static";
1890 }
George Liu0fda0f12021-11-16 10:06:17 +08001891 else if (
1892 modeValue ==
1893 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001894 {
1895 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1896 }
George Liu0fda0f12021-11-16 10:06:17 +08001897 else if (modeValue ==
1898 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001899 {
1900 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1901 }
George Liu0fda0f12021-11-16 10:06:17 +08001902 else if (modeValue ==
1903 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001904 {
1905 aResp->res.jsonValue["PowerMode"] = "OEM";
1906 }
1907 else
1908 {
1909 // Any other values would be invalid
1910 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1911 messages::internalError(aResp->res);
1912 }
1913}
1914
1915/**
1916 * @brief Retrieves system power mode
1917 *
1918 * @param[in] aResp Shared pointer for generating response message.
1919 *
1920 * @return None.
1921 */
1922inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1923{
1924 BMCWEB_LOG_DEBUG << "Get power mode.";
1925
1926 // Get Power Mode object path:
1927 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001928 [aResp](const boost::system::error_code ec,
1929 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001930 if (ec)
1931 {
1932 BMCWEB_LOG_DEBUG
1933 << "DBUS response error on Power.Mode GetSubTree " << ec;
1934 // This is an optional D-Bus object so just return if
1935 // error occurs
1936 return;
1937 }
1938 if (subtree.empty())
1939 {
1940 // As noted above, this is an optional interface so just return
1941 // if there is no instance found
1942 return;
1943 }
1944 if (subtree.size() > 1)
1945 {
1946 // More then one PowerMode object is not supported and is an
1947 // error
1948 BMCWEB_LOG_DEBUG
1949 << "Found more than 1 system D-Bus Power.Mode objects: "
1950 << subtree.size();
1951 messages::internalError(aResp->res);
1952 return;
1953 }
1954 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1955 {
1956 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1957 messages::internalError(aResp->res);
1958 return;
1959 }
1960 const std::string& path = subtree[0].first;
1961 const std::string& service = subtree[0].second.begin()->first;
1962 if (service.empty())
1963 {
1964 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1965 messages::internalError(aResp->res);
1966 return;
1967 }
1968 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001969 sdbusplus::asio::getProperty<std::string>(
1970 *crow::connections::systemBus, service, path,
1971 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001972 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001973 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001974 if (ec)
1975 {
1976 BMCWEB_LOG_DEBUG
1977 << "DBUS response error on PowerMode Get: " << ec;
1978 messages::internalError(aResp->res);
1979 return;
1980 }
1981
Chris Cain3a2d04242021-05-28 16:57:10 -05001982 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1983 {"Static", "MaximumPerformance", "PowerSaving"};
1984
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001985 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1986 translatePowerMode(aResp, pmode);
1987 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001988 },
1989 "xyz.openbmc_project.ObjectMapper",
1990 "/xyz/openbmc_project/object_mapper",
1991 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1992 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1993}
1994
1995/**
1996 * @brief Validate the specified mode is valid and return the PowerMode
1997 * name associated with that string
1998 *
1999 * @param[in] aResp Shared pointer for generating response message.
2000 * @param[in] modeString String representing the desired PowerMode
2001 *
2002 * @return PowerMode value or empty string if mode is not valid
2003 */
2004inline std::string
2005 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2006 const std::string& modeString)
2007{
2008 std::string mode;
2009
2010 if (modeString == "Static")
2011 {
2012 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2013 }
2014 else if (modeString == "MaximumPerformance")
2015 {
George Liu0fda0f12021-11-16 10:06:17 +08002016 mode =
2017 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002018 }
2019 else if (modeString == "PowerSaving")
2020 {
2021 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2022 }
2023 else
2024 {
2025 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2026 }
2027 return mode;
2028}
2029
2030/**
2031 * @brief Sets system power mode.
2032 *
2033 * @param[in] aResp Shared pointer for generating response message.
2034 * @param[in] pmode System power mode from request.
2035 *
2036 * @return None.
2037 */
2038inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2039 const std::string& pmode)
2040{
2041 BMCWEB_LOG_DEBUG << "Set power mode.";
2042
2043 std::string powerMode = validatePowerMode(aResp, pmode);
2044 if (powerMode.empty())
2045 {
2046 return;
2047 }
2048
2049 // Get Power Mode object path:
2050 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002051 [aResp,
2052 powerMode](const boost::system::error_code ec,
2053 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002054 if (ec)
2055 {
2056 BMCWEB_LOG_DEBUG
2057 << "DBUS response error on Power.Mode GetSubTree " << ec;
2058 // This is an optional D-Bus object, but user attempted to patch
2059 messages::internalError(aResp->res);
2060 return;
2061 }
2062 if (subtree.empty())
2063 {
2064 // This is an optional D-Bus object, but user attempted to patch
2065 messages::resourceNotFound(aResp->res, "ComputerSystem",
2066 "PowerMode");
2067 return;
2068 }
2069 if (subtree.size() > 1)
2070 {
2071 // More then one PowerMode object is not supported and is an
2072 // error
2073 BMCWEB_LOG_DEBUG
2074 << "Found more than 1 system D-Bus Power.Mode objects: "
2075 << subtree.size();
2076 messages::internalError(aResp->res);
2077 return;
2078 }
2079 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2080 {
2081 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2082 messages::internalError(aResp->res);
2083 return;
2084 }
2085 const std::string& path = subtree[0].first;
2086 const std::string& service = subtree[0].second.begin()->first;
2087 if (service.empty())
2088 {
2089 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2090 messages::internalError(aResp->res);
2091 return;
2092 }
2093
2094 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2095 << path;
2096
2097 // Set the Power Mode property
2098 crow::connections::systemBus->async_method_call(
2099 [aResp](const boost::system::error_code ec) {
2100 if (ec)
2101 {
2102 messages::internalError(aResp->res);
2103 return;
2104 }
2105 },
2106 service, path, "org.freedesktop.DBus.Properties", "Set",
2107 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002108 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002109 },
2110 "xyz.openbmc_project.ObjectMapper",
2111 "/xyz/openbmc_project/object_mapper",
2112 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2113 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2114}
2115
2116/**
Yong Li51709ff2019-09-30 14:13:04 +08002117 * @brief Translates watchdog timeout action DBUS property value to redfish.
2118 *
2119 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2120 *
2121 * @return Returns as a string, the timeout action in Redfish terms. If
2122 * translation cannot be done, returns an empty string.
2123 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002124inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002125{
2126 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2127 {
2128 return "None";
2129 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002130 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002131 {
2132 return "ResetSystem";
2133 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002134 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002135 {
2136 return "PowerDown";
2137 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002138 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002139 {
2140 return "PowerCycle";
2141 }
2142
2143 return "";
2144}
2145
2146/**
Yong Lic45f0082019-10-10 14:19:01 +08002147 *@brief Translates timeout action from Redfish to DBUS property value.
2148 *
2149 *@param[in] rfAction The timeout action in Redfish.
2150 *
2151 *@return Returns as a string, the time_out action as expected by DBUS.
2152 *If translation cannot be done, returns an empty string.
2153 */
2154
Ed Tanous23a21a12020-07-25 04:45:05 +00002155inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002156{
2157 if (rfAction == "None")
2158 {
2159 return "xyz.openbmc_project.State.Watchdog.Action.None";
2160 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002161 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002162 {
2163 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2164 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002165 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002166 {
2167 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2168 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002169 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002170 {
2171 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2172 }
2173
2174 return "";
2175}
2176
2177/**
Yong Li51709ff2019-09-30 14:13:04 +08002178 * @brief Retrieves host watchdog timer properties over DBUS
2179 *
2180 * @param[in] aResp Shared pointer for completing asynchronous calls.
2181 *
2182 * @return None.
2183 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002184inline void
2185 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002186{
2187 BMCWEB_LOG_DEBUG << "Get host watchodg";
2188 crow::connections::systemBus->async_method_call(
2189 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002190 const dbus::utility::DBusPropertiesMap& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002191 if (ec)
2192 {
2193 // watchdog service is stopped
2194 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2195 return;
2196 }
2197
2198 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2199
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002200 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002201 aResp->res.jsonValue["HostWatchdogTimer"];
2202
2203 // watchdog service is running/enabled
2204 hostWatchdogTimer["Status"]["State"] = "Enabled";
2205
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002206 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002207 {
2208 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2209 if (property.first == "Enabled")
2210 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002211 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002212
Ed Tanouse662eae2022-01-25 10:39:19 -08002213 if (state == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002214 {
2215 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002216 return;
Yong Li51709ff2019-09-30 14:13:04 +08002217 }
2218
2219 hostWatchdogTimer["FunctionEnabled"] = *state;
2220 }
2221 else if (property.first == "ExpireAction")
2222 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002223 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002224 std::get_if<std::string>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002225 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002226 {
2227 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002228 return;
Yong Li51709ff2019-09-30 14:13:04 +08002229 }
2230
2231 std::string action = dbusToRfWatchdogAction(*s);
2232 if (action.empty())
2233 {
2234 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002235 return;
Yong Li51709ff2019-09-30 14:13:04 +08002236 }
2237 hostWatchdogTimer["TimeoutAction"] = action;
2238 }
2239 }
2240 },
2241 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2242 "org.freedesktop.DBus.Properties", "GetAll",
2243 "xyz.openbmc_project.State.Watchdog");
2244}
2245
2246/**
Yong Lic45f0082019-10-10 14:19:01 +08002247 * @brief Sets Host WatchDog Timer properties.
2248 *
2249 * @param[in] aResp Shared pointer for generating response message.
2250 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2251 * RF request.
2252 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2253 *
2254 * @return None.
2255 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002256inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002257 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002258 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002259{
2260 BMCWEB_LOG_DEBUG << "Set host watchdog";
2261
2262 if (wdtTimeOutAction)
2263 {
2264 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2265 // check if TimeOut Action is Valid
2266 if (wdtTimeOutActStr.empty())
2267 {
2268 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2269 << *wdtTimeOutAction;
2270 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2271 "TimeoutAction");
2272 return;
2273 }
2274
2275 crow::connections::systemBus->async_method_call(
2276 [aResp](const boost::system::error_code ec) {
2277 if (ec)
2278 {
2279 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2280 messages::internalError(aResp->res);
2281 return;
2282 }
2283 },
2284 "xyz.openbmc_project.Watchdog",
2285 "/xyz/openbmc_project/watchdog/host0",
2286 "org.freedesktop.DBus.Properties", "Set",
2287 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002288 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002289 }
2290
2291 if (wdtEnable)
2292 {
2293 crow::connections::systemBus->async_method_call(
2294 [aResp](const boost::system::error_code ec) {
2295 if (ec)
2296 {
2297 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2298 messages::internalError(aResp->res);
2299 return;
2300 }
2301 },
2302 "xyz.openbmc_project.Watchdog",
2303 "/xyz/openbmc_project/watchdog/host0",
2304 "org.freedesktop.DBus.Properties", "Set",
2305 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002306 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002307 }
2308}
2309
Chris Cain37bbf982021-09-20 10:53:09 -05002310using ipsPropertiesType =
2311 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2312/**
2313 * @brief Parse the Idle Power Saver properties into json
2314 *
2315 * @param[in] aResp Shared pointer for completing asynchronous calls.
2316 * @param[in] properties IPS property data from DBus.
2317 *
2318 * @return true if successful
2319 */
Ed Tanousf6674222021-11-13 09:41:41 -08002320inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2321 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002322{
2323 for (const auto& property : properties)
2324 {
2325 if (property.first == "Enabled")
2326 {
2327 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002328 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002329 {
2330 return false;
2331 }
2332 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2333 }
2334 else if (property.first == "EnterUtilizationPercent")
2335 {
2336 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002337 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002338 {
2339 return false;
2340 }
2341 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2342 }
2343 else if (property.first == "EnterDwellTime")
2344 {
2345 // Convert Dbus time from milliseconds to seconds
2346 const uint64_t* timeMilliseconds =
2347 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002348 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002349 {
2350 return false;
2351 }
2352 const std::chrono::duration<uint64_t, std::milli> ms(
2353 *timeMilliseconds);
2354 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2355 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2356 .count();
2357 }
2358 else if (property.first == "ExitUtilizationPercent")
2359 {
2360 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002361 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002362 {
2363 return false;
2364 }
2365 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2366 }
2367 else if (property.first == "ExitDwellTime")
2368 {
2369 // Convert Dbus time from milliseconds to seconds
2370 const uint64_t* timeMilliseconds =
2371 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002372 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002373 {
2374 return false;
2375 }
2376 const std::chrono::duration<uint64_t, std::milli> ms(
2377 *timeMilliseconds);
2378 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2379 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2380 .count();
2381 }
2382 else
2383 {
2384 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2385 << property.first;
2386 }
2387 }
2388
2389 return true;
2390}
2391
2392/**
2393 * @brief Retrieves host watchdog timer properties over DBUS
2394 *
2395 * @param[in] aResp Shared pointer for completing asynchronous calls.
2396 *
2397 * @return None.
2398 */
2399inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2400{
2401 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2402
2403 // Get IdlePowerSaver object path:
2404 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002405 [aResp](const boost::system::error_code ec,
2406 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain37bbf982021-09-20 10:53:09 -05002407 if (ec)
2408 {
2409 BMCWEB_LOG_DEBUG
2410 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2411 << ec;
2412 messages::internalError(aResp->res);
2413 return;
2414 }
2415 if (subtree.empty())
2416 {
2417 // This is an optional interface so just return
2418 // if there is no instance found
2419 BMCWEB_LOG_DEBUG << "No instances found";
2420 return;
2421 }
2422 if (subtree.size() > 1)
2423 {
2424 // More then one PowerIdlePowerSaver object is not supported and
2425 // is an error
2426 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2427 "Power.IdlePowerSaver objects: "
2428 << subtree.size();
2429 messages::internalError(aResp->res);
2430 return;
2431 }
2432 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2433 {
2434 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2435 messages::internalError(aResp->res);
2436 return;
2437 }
2438 const std::string& path = subtree[0].first;
2439 const std::string& service = subtree[0].second.begin()->first;
2440 if (service.empty())
2441 {
2442 BMCWEB_LOG_DEBUG
2443 << "Power.IdlePowerSaver service mapper error!";
2444 messages::internalError(aResp->res);
2445 return;
2446 }
2447
2448 // Valid IdlePowerSaver object found, now read the current values
2449 crow::connections::systemBus->async_method_call(
2450 [aResp](const boost::system::error_code ec,
2451 ipsPropertiesType& properties) {
2452 if (ec)
2453 {
2454 BMCWEB_LOG_ERROR
2455 << "DBUS response error on IdlePowerSaver GetAll: "
2456 << ec;
2457 messages::internalError(aResp->res);
2458 return;
2459 }
2460
Ed Tanouse05aec52022-01-25 10:28:56 -08002461 if (!parseIpsProperties(aResp, properties))
Chris Cain37bbf982021-09-20 10:53:09 -05002462 {
2463 messages::internalError(aResp->res);
2464 return;
2465 }
2466 },
2467 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2468 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2469 },
2470 "xyz.openbmc_project.ObjectMapper",
2471 "/xyz/openbmc_project/object_mapper",
2472 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2473 std::array<const char*, 1>{
2474 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2475
2476 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2477}
2478
2479/**
2480 * @brief Sets Idle Power Saver properties.
2481 *
2482 * @param[in] aResp Shared pointer for generating response message.
2483 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2484 * RF request.
2485 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2486 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2487 * before entering idle state.
2488 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2489 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2490 * before exiting idle state
2491 *
2492 * @return None.
2493 */
2494inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2495 const std::optional<bool> ipsEnable,
2496 const std::optional<uint8_t> ipsEnterUtil,
2497 const std::optional<uint64_t> ipsEnterTime,
2498 const std::optional<uint8_t> ipsExitUtil,
2499 const std::optional<uint64_t> ipsExitTime)
2500{
2501 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2502
2503 // Get IdlePowerSaver object path:
2504 crow::connections::systemBus->async_method_call(
2505 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002506 ipsExitTime](const boost::system::error_code ec,
2507 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain37bbf982021-09-20 10:53:09 -05002508 if (ec)
2509 {
2510 BMCWEB_LOG_DEBUG
2511 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2512 << ec;
2513 messages::internalError(aResp->res);
2514 return;
2515 }
2516 if (subtree.empty())
2517 {
2518 // This is an optional D-Bus object, but user attempted to patch
2519 messages::resourceNotFound(aResp->res, "ComputerSystem",
2520 "IdlePowerSaver");
2521 return;
2522 }
2523 if (subtree.size() > 1)
2524 {
2525 // More then one PowerIdlePowerSaver object is not supported and
2526 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002527 BMCWEB_LOG_DEBUG
2528 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2529 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002530 messages::internalError(aResp->res);
2531 return;
2532 }
2533 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2534 {
2535 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2536 messages::internalError(aResp->res);
2537 return;
2538 }
2539 const std::string& path = subtree[0].first;
2540 const std::string& service = subtree[0].second.begin()->first;
2541 if (service.empty())
2542 {
2543 BMCWEB_LOG_DEBUG
2544 << "Power.IdlePowerSaver service mapper error!";
2545 messages::internalError(aResp->res);
2546 return;
2547 }
2548
2549 // Valid Power IdlePowerSaver object found, now set any values that
2550 // need to be updated
2551
2552 if (ipsEnable)
2553 {
2554 crow::connections::systemBus->async_method_call(
2555 [aResp](const boost::system::error_code ec) {
2556 if (ec)
2557 {
2558 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2559 messages::internalError(aResp->res);
2560 return;
2561 }
2562 },
2563 service, path, "org.freedesktop.DBus.Properties", "Set",
2564 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002565 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002566 }
2567 if (ipsEnterUtil)
2568 {
2569 crow::connections::systemBus->async_method_call(
2570 [aResp](const boost::system::error_code ec) {
2571 if (ec)
2572 {
2573 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2574 messages::internalError(aResp->res);
2575 return;
2576 }
2577 },
2578 service, path, "org.freedesktop.DBus.Properties", "Set",
2579 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2580 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002581 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002582 }
2583 if (ipsEnterTime)
2584 {
2585 // Convert from seconds into milliseconds for DBus
2586 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2587 crow::connections::systemBus->async_method_call(
2588 [aResp](const boost::system::error_code ec) {
2589 if (ec)
2590 {
2591 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2592 messages::internalError(aResp->res);
2593 return;
2594 }
2595 },
2596 service, path, "org.freedesktop.DBus.Properties", "Set",
2597 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002598 "EnterDwellTime",
2599 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002600 }
2601 if (ipsExitUtil)
2602 {
2603 crow::connections::systemBus->async_method_call(
2604 [aResp](const boost::system::error_code ec) {
2605 if (ec)
2606 {
2607 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2608 messages::internalError(aResp->res);
2609 return;
2610 }
2611 },
2612 service, path, "org.freedesktop.DBus.Properties", "Set",
2613 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2614 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002615 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002616 }
2617 if (ipsExitTime)
2618 {
2619 // Convert from seconds into milliseconds for DBus
2620 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2621 crow::connections::systemBus->async_method_call(
2622 [aResp](const boost::system::error_code ec) {
2623 if (ec)
2624 {
2625 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2626 messages::internalError(aResp->res);
2627 return;
2628 }
2629 },
2630 service, path, "org.freedesktop.DBus.Properties", "Set",
2631 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002632 "ExitDwellTime",
2633 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002634 }
2635 },
2636 "xyz.openbmc_project.ObjectMapper",
2637 "/xyz/openbmc_project/object_mapper",
2638 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2639 std::array<const char*, 1>{
2640 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2641
2642 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2643}
2644
Yong Lic45f0082019-10-10 14:19:01 +08002645/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002646 * SystemsCollection derived class for delivering ComputerSystems Collection
2647 * Schema
2648 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002649inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002650{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002651 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002652 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002653 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002654 [&app](const crow::Request& req,
2655 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2656 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2657 {
2658 return;
2659 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002660 asyncResp->res.jsonValue["@odata.type"] =
2661 "#ComputerSystemCollection.ComputerSystemCollection";
2662 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2663 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002664
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002665 sdbusplus::asio::getProperty<std::string>(
2666 *crow::connections::systemBus,
2667 "xyz.openbmc_project.Settings",
2668 "/xyz/openbmc_project/network/hypervisor",
2669 "xyz.openbmc_project.Network.SystemConfiguration",
2670 "HostName",
2671 [asyncResp](const boost::system::error_code ec,
2672 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002673 nlohmann::json& ifaceArray =
2674 asyncResp->res.jsonValue["Members"];
2675 ifaceArray = nlohmann::json::array();
2676 auto& count =
2677 asyncResp->res.jsonValue["Members@odata.count"];
2678 ifaceArray.push_back(
2679 {{"@odata.id", "/redfish/v1/Systems/system"}});
2680 count = ifaceArray.size();
2681 if (!ec)
2682 {
2683 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2684 ifaceArray.push_back(
2685 {{"@odata.id",
2686 "/redfish/v1/Systems/hypervisor"}});
2687 count = ifaceArray.size();
2688 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002689 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002690 });
2691}
Sunitha Harish462023a2020-02-19 08:34:59 -06002692
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002693/**
2694 * Function transceives data with dbus directly.
2695 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002696inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002697{
2698 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2699 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2700 constexpr char const* interfaceName =
2701 "xyz.openbmc_project.Control.Host.NMI";
2702 constexpr char const* method = "NMI";
2703
2704 crow::connections::systemBus->async_method_call(
2705 [asyncResp](const boost::system::error_code ec) {
2706 if (ec)
2707 {
2708 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2709 messages::internalError(asyncResp->res);
2710 return;
2711 }
2712 messages::success(asyncResp->res);
2713 },
2714 serviceName, objectPath, interfaceName, method);
2715}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002716
2717/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002718 * SystemActionsReset class supports handle POST method for Reset action.
2719 * The class retrieves and sends data directly to D-Bus.
2720 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002721inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002722{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002723 /**
2724 * Function handles POST method request.
2725 * Analyzes POST body message before sends Reset request data to D-Bus.
2726 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002727 BMCWEB_ROUTE(app,
2728 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002729 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002730 .methods(
2731 boost::beast::http::verb::
Ed Tanous45ca1b82022-03-25 13:07:27 -07002732 post)([&app](
2733 const crow::Request& req,
2734 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2735 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2736 {
2737 return;
2738 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002739 std::string resetType;
Willy Tu15ed6782021-12-14 11:03:16 -08002740 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2741 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002742 {
2743 return;
2744 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002745
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002746 // Get the command and host vs. chassis
2747 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002748 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002749 if ((resetType == "On") || (resetType == "ForceOn"))
2750 {
2751 command = "xyz.openbmc_project.State.Host.Transition.On";
2752 hostCommand = true;
2753 }
2754 else if (resetType == "ForceOff")
2755 {
2756 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2757 hostCommand = false;
2758 }
2759 else if (resetType == "ForceRestart")
2760 {
2761 command =
2762 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2763 hostCommand = true;
2764 }
2765 else if (resetType == "GracefulShutdown")
2766 {
2767 command = "xyz.openbmc_project.State.Host.Transition.Off";
2768 hostCommand = true;
2769 }
2770 else if (resetType == "GracefulRestart")
2771 {
George Liu0fda0f12021-11-16 10:06:17 +08002772 command =
2773 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002774 hostCommand = true;
2775 }
2776 else if (resetType == "PowerCycle")
2777 {
2778 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2779 hostCommand = true;
2780 }
2781 else if (resetType == "Nmi")
2782 {
2783 doNMI(asyncResp);
2784 return;
2785 }
2786 else
2787 {
2788 messages::actionParameterUnknown(asyncResp->res, "Reset",
2789 resetType);
2790 return;
2791 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002792
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002793 if (hostCommand)
2794 {
2795 crow::connections::systemBus->async_method_call(
2796 [asyncResp, resetType](const boost::system::error_code ec) {
2797 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002798 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002799 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2800 if (ec.value() ==
2801 boost::asio::error::invalid_argument)
2802 {
2803 messages::actionParameterNotSupported(
2804 asyncResp->res, resetType, "Reset");
2805 }
2806 else
2807 {
2808 messages::internalError(asyncResp->res);
2809 }
2810 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002811 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002812 messages::success(asyncResp->res);
2813 },
2814 "xyz.openbmc_project.State.Host",
2815 "/xyz/openbmc_project/state/host0",
2816 "org.freedesktop.DBus.Properties", "Set",
2817 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002818 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 }
2820 else
2821 {
2822 crow::connections::systemBus->async_method_call(
2823 [asyncResp, resetType](const boost::system::error_code ec) {
2824 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002825 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002826 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2827 if (ec.value() ==
2828 boost::asio::error::invalid_argument)
2829 {
2830 messages::actionParameterNotSupported(
2831 asyncResp->res, resetType, "Reset");
2832 }
2833 else
2834 {
2835 messages::internalError(asyncResp->res);
2836 }
2837 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002838 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839 messages::success(asyncResp->res);
2840 },
2841 "xyz.openbmc_project.State.Chassis",
2842 "/xyz/openbmc_project/state/chassis0",
2843 "org.freedesktop.DBus.Properties", "Set",
2844 "xyz.openbmc_project.State.Chassis",
2845 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002846 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002847 }
2848 });
2849}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002850
2851/**
Ed Tanous66173382018-08-15 18:20:59 -07002852 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002853 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002854inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002855{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002856
Ed Tanous1abe55e2018-09-05 08:30:59 -07002857 /**
2858 * Functions triggers appropriate requests on DBus
2859 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002860 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002861 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous45ca1b82022-03-25 13:07:27 -07002862 .methods(boost::beast::http::verb::get)([&app](const crow::Request& req,
2863 const std::shared_ptr<
2864 bmcweb::AsyncResp>&
2865 asyncResp) {
2866 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2867 {
2868 return;
2869 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002870 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002871 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002872 asyncResp->res.jsonValue["Name"] = "system";
2873 asyncResp->res.jsonValue["Id"] = "system";
2874 asyncResp->res.jsonValue["SystemType"] = "Physical";
2875 asyncResp->res.jsonValue["Description"] = "Computer System";
2876 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2877 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2878 "Disabled";
2879 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2880 uint64_t(0);
2881 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2882 "Disabled";
2883 asyncResp->res.jsonValue["@odata.id"] =
2884 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002885
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002886 asyncResp->res.jsonValue["Processors"] = {
2887 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2888 asyncResp->res.jsonValue["Memory"] = {
2889 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2890 asyncResp->res.jsonValue["Storage"] = {
2891 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002892
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002893 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2894 {"target",
2895 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2896 {"@Redfish.ActionInfo",
2897 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002898
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002899 asyncResp->res.jsonValue["LogServices"] = {
2900 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002901
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002902 asyncResp->res.jsonValue["Bios"] = {
2903 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002904
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002905 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2906 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002907
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002908 asyncResp->res.jsonValue["Status"] = {
2909 {"Health", "OK"},
2910 {"State", "Enabled"},
2911 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002912
2913 // Fill in SerialConsole info
2914 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2915 15;
2916 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2917 {"ServiceEnabled", true},
2918 };
2919 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2920 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2921 {"ServiceEnabled", true},
2922 {"Port", 2200},
2923 // https://github.com/openbmc/docs/blob/master/console.md
2924 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2925 };
2926
2927#ifdef BMCWEB_ENABLE_KVM
2928 // Fill in GraphicalConsole info
2929 asyncResp->res.jsonValue["GraphicalConsole"] = {
2930 {"ServiceEnabled", true},
2931 {"MaxConcurrentSessions", 4},
2932 {"ConnectTypesSupported", {"KVMIP"}},
2933 };
2934#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002935 constexpr const std::array<const char*, 4> inventoryForSystems = {
2936 "xyz.openbmc_project.Inventory.Item.Dimm",
2937 "xyz.openbmc_project.Inventory.Item.Cpu",
2938 "xyz.openbmc_project.Inventory.Item.Drive",
2939 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002940
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002941 auto health = std::make_shared<HealthPopulate>(asyncResp);
2942 crow::connections::systemBus->async_method_call(
2943 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002944 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002945 if (ec)
2946 {
2947 // no inventory
2948 return;
2949 }
2950
Ed Tanous914e2d52022-01-07 11:38:34 -08002951 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002952 },
2953 "xyz.openbmc_project.ObjectMapper",
2954 "/xyz/openbmc_project/object_mapper",
2955 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2956 int32_t(0), inventoryForSystems);
2957
2958 health->populate();
2959
2960 getMainChassisId(
2961 asyncResp, [](const std::string& chassisId,
2962 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2963 aRsp->res.jsonValue["Links"]["Chassis"] = {
2964 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2965 });
2966
2967 getLocationIndicatorActive(asyncResp);
2968 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2969 getIndicatorLedState(asyncResp);
2970 getComputerSystem(asyncResp, health);
2971 getHostState(asyncResp);
2972 getBootProperties(asyncResp);
2973 getBootProgress(asyncResp);
2974 getPCIeDeviceList(asyncResp, "PCIeDevices");
2975 getHostWatchdogTimer(asyncResp);
2976 getPowerRestorePolicy(asyncResp);
2977 getAutomaticRetry(asyncResp);
2978 getLastResetTime(asyncResp);
2979#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2980 getProvisioningStatus(asyncResp);
2981#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002982 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002983 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05002984 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002985 });
2986 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002987 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002988 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002989 [&app](const crow::Request& req,
2990 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2991 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2992 {
2993 return;
2994 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002995 std::optional<bool> locationIndicatorActive;
2996 std::optional<std::string> indicatorLed;
2997 std::optional<nlohmann::json> bootProps;
2998 std::optional<nlohmann::json> wdtTimerProps;
2999 std::optional<std::string> assetTag;
3000 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003001 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003002 std::optional<nlohmann::json> ipsProps;
Willy Tu15ed6782021-12-14 11:03:16 -08003003 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003004 req, asyncResp->res, "IndicatorLED", indicatorLed,
3005 "LocationIndicatorActive", locationIndicatorActive,
Jiaqing Zhao49328a22022-04-22 21:07:25 +08003006 "Boot", bootProps, "HostWatchdogTimer", wdtTimerProps,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003007 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003008 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3009 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003010 {
James Feistb49ac872019-05-21 15:12:01 -07003011 return;
3012 }
3013
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003014 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003015
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003016 if (assetTag)
3017 {
3018 setAssetTag(asyncResp, *assetTag);
3019 }
James Feistb49ac872019-05-21 15:12:01 -07003020
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003021 if (wdtTimerProps)
3022 {
3023 std::optional<bool> wdtEnable;
3024 std::optional<std::string> wdtTimeOutAction;
3025
3026 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3027 "FunctionEnabled", wdtEnable,
3028 "TimeoutAction", wdtTimeOutAction))
3029 {
3030 return;
3031 }
3032 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3033 }
3034
3035 if (bootProps)
3036 {
3037 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003038 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039 std::optional<std::string> bootEnable;
3040 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003041 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003042
3043 if (!json_util::readJson(
3044 *bootProps, asyncResp->res,
3045 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003046 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003047 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003048 "AutomaticRetryConfig", automaticRetryConfig,
3049 "TrustedModuleRequiredToBoot",
3050 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003051 {
3052 return;
3053 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003054
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003055 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003056 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003057 setBootProperties(asyncResp, bootSource, bootType,
3058 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003059 }
3060 if (automaticRetryConfig)
3061 {
3062 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3063 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003064
3065 if (trustedModuleRequiredToBoot)
3066 {
3067 setTrustedModuleRequiredToBoot(
3068 asyncResp, *trustedModuleRequiredToBoot);
3069 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003070 }
3071
3072 if (locationIndicatorActive)
3073 {
3074 setLocationIndicatorActive(asyncResp,
3075 *locationIndicatorActive);
3076 }
3077
3078 // TODO (Gunnar): Remove IndicatorLED after enough time has
3079 // passed
3080 if (indicatorLed)
3081 {
3082 setIndicatorLedState(asyncResp, *indicatorLed);
3083 asyncResp->res.addHeader(
3084 boost::beast::http::field::warning,
3085 "299 - \"IndicatorLED is deprecated. Use "
3086 "LocationIndicatorActive instead.\"");
3087 }
3088
3089 if (powerRestorePolicy)
3090 {
3091 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3092 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003093
3094 if (powerMode)
3095 {
3096 setPowerMode(asyncResp, *powerMode);
3097 }
Chris Cain37bbf982021-09-20 10:53:09 -05003098
3099 if (ipsProps)
3100 {
3101 std::optional<bool> ipsEnable;
3102 std::optional<uint8_t> ipsEnterUtil;
3103 std::optional<uint64_t> ipsEnterTime;
3104 std::optional<uint8_t> ipsExitUtil;
3105 std::optional<uint64_t> ipsExitTime;
3106
3107 if (!json_util::readJson(
3108 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3109 "EnterUtilizationPercent", ipsEnterUtil,
3110 "EnterDwellTimeSeconds", ipsEnterTime,
3111 "ExitUtilizationPercent", ipsExitUtil,
3112 "ExitDwellTimeSeconds", ipsExitTime))
3113 {
3114 return;
3115 }
3116 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3117 ipsEnterTime, ipsExitUtil, ipsExitTime);
3118 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003119 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003120}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303121
3122/**
3123 * SystemResetActionInfo derived class for delivering Computer Systems
3124 * ResetType AllowableValues using ResetInfo schema.
3125 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003126inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303127{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303128
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303129 /**
3130 * Functions triggers appropriate requests on DBus
3131 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003132 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003133 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003134 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003135 [&app](const crow::Request& req,
3136 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3137 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
3138 {
3139 return;
3140 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003141 asyncResp->res.jsonValue = {
3142 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3143 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3144 {"Name", "Reset Action Info"},
3145 {"Id", "ResetActionInfo"},
3146 {"Parameters",
3147 {{{"Name", "ResetType"},
3148 {"Required", true},
3149 {"DataType", "String"},
3150 {"AllowableValues",
3151 {"On", "ForceOff", "ForceOn", "ForceRestart",
3152 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3153 "Nmi"}}}}}};
3154 });
3155}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003156} // namespace redfish