blob: 83f9dadf3e9af7f8aca1027e1d1c2d81d4c77f5a [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{
1887 std::string modeString;
1888
George Liu0fda0f12021-11-16 10:06:17 +08001889 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001890 {
1891 aResp->res.jsonValue["PowerMode"] = "Static";
1892 }
George Liu0fda0f12021-11-16 10:06:17 +08001893 else if (
1894 modeValue ==
1895 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001896 {
1897 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1898 }
George Liu0fda0f12021-11-16 10:06:17 +08001899 else if (modeValue ==
1900 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001901 {
1902 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1903 }
George Liu0fda0f12021-11-16 10:06:17 +08001904 else if (modeValue ==
1905 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001906 {
1907 aResp->res.jsonValue["PowerMode"] = "OEM";
1908 }
1909 else
1910 {
1911 // Any other values would be invalid
1912 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1913 messages::internalError(aResp->res);
1914 }
1915}
1916
1917/**
1918 * @brief Retrieves system power mode
1919 *
1920 * @param[in] aResp Shared pointer for generating response message.
1921 *
1922 * @return None.
1923 */
1924inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1925{
1926 BMCWEB_LOG_DEBUG << "Get power mode.";
1927
1928 // Get Power Mode object path:
1929 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001930 [aResp](const boost::system::error_code ec,
1931 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001932 if (ec)
1933 {
1934 BMCWEB_LOG_DEBUG
1935 << "DBUS response error on Power.Mode GetSubTree " << ec;
1936 // This is an optional D-Bus object so just return if
1937 // error occurs
1938 return;
1939 }
1940 if (subtree.empty())
1941 {
1942 // As noted above, this is an optional interface so just return
1943 // if there is no instance found
1944 return;
1945 }
1946 if (subtree.size() > 1)
1947 {
1948 // More then one PowerMode object is not supported and is an
1949 // error
1950 BMCWEB_LOG_DEBUG
1951 << "Found more than 1 system D-Bus Power.Mode objects: "
1952 << subtree.size();
1953 messages::internalError(aResp->res);
1954 return;
1955 }
1956 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1957 {
1958 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1959 messages::internalError(aResp->res);
1960 return;
1961 }
1962 const std::string& path = subtree[0].first;
1963 const std::string& service = subtree[0].second.begin()->first;
1964 if (service.empty())
1965 {
1966 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1967 messages::internalError(aResp->res);
1968 return;
1969 }
1970 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001971 sdbusplus::asio::getProperty<std::string>(
1972 *crow::connections::systemBus, service, path,
1973 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001974 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001975 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001976 if (ec)
1977 {
1978 BMCWEB_LOG_DEBUG
1979 << "DBUS response error on PowerMode Get: " << ec;
1980 messages::internalError(aResp->res);
1981 return;
1982 }
1983
Chris Cain3a2d04242021-05-28 16:57:10 -05001984 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1985 {"Static", "MaximumPerformance", "PowerSaving"};
1986
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001987 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1988 translatePowerMode(aResp, pmode);
1989 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001990 },
1991 "xyz.openbmc_project.ObjectMapper",
1992 "/xyz/openbmc_project/object_mapper",
1993 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1994 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1995}
1996
1997/**
1998 * @brief Validate the specified mode is valid and return the PowerMode
1999 * name associated with that string
2000 *
2001 * @param[in] aResp Shared pointer for generating response message.
2002 * @param[in] modeString String representing the desired PowerMode
2003 *
2004 * @return PowerMode value or empty string if mode is not valid
2005 */
2006inline std::string
2007 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2008 const std::string& modeString)
2009{
2010 std::string mode;
2011
2012 if (modeString == "Static")
2013 {
2014 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2015 }
2016 else if (modeString == "MaximumPerformance")
2017 {
George Liu0fda0f12021-11-16 10:06:17 +08002018 mode =
2019 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002020 }
2021 else if (modeString == "PowerSaving")
2022 {
2023 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2024 }
2025 else
2026 {
2027 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2028 }
2029 return mode;
2030}
2031
2032/**
2033 * @brief Sets system power mode.
2034 *
2035 * @param[in] aResp Shared pointer for generating response message.
2036 * @param[in] pmode System power mode from request.
2037 *
2038 * @return None.
2039 */
2040inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2041 const std::string& pmode)
2042{
2043 BMCWEB_LOG_DEBUG << "Set power mode.";
2044
2045 std::string powerMode = validatePowerMode(aResp, pmode);
2046 if (powerMode.empty())
2047 {
2048 return;
2049 }
2050
2051 // Get Power Mode object path:
2052 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002053 [aResp,
2054 powerMode](const boost::system::error_code ec,
2055 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002056 if (ec)
2057 {
2058 BMCWEB_LOG_DEBUG
2059 << "DBUS response error on Power.Mode GetSubTree " << ec;
2060 // This is an optional D-Bus object, but user attempted to patch
2061 messages::internalError(aResp->res);
2062 return;
2063 }
2064 if (subtree.empty())
2065 {
2066 // This is an optional D-Bus object, but user attempted to patch
2067 messages::resourceNotFound(aResp->res, "ComputerSystem",
2068 "PowerMode");
2069 return;
2070 }
2071 if (subtree.size() > 1)
2072 {
2073 // More then one PowerMode object is not supported and is an
2074 // error
2075 BMCWEB_LOG_DEBUG
2076 << "Found more than 1 system D-Bus Power.Mode objects: "
2077 << subtree.size();
2078 messages::internalError(aResp->res);
2079 return;
2080 }
2081 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2082 {
2083 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2084 messages::internalError(aResp->res);
2085 return;
2086 }
2087 const std::string& path = subtree[0].first;
2088 const std::string& service = subtree[0].second.begin()->first;
2089 if (service.empty())
2090 {
2091 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2092 messages::internalError(aResp->res);
2093 return;
2094 }
2095
2096 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2097 << path;
2098
2099 // Set the Power Mode property
2100 crow::connections::systemBus->async_method_call(
2101 [aResp](const boost::system::error_code ec) {
2102 if (ec)
2103 {
2104 messages::internalError(aResp->res);
2105 return;
2106 }
2107 },
2108 service, path, "org.freedesktop.DBus.Properties", "Set",
2109 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002110 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002111 },
2112 "xyz.openbmc_project.ObjectMapper",
2113 "/xyz/openbmc_project/object_mapper",
2114 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2115 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2116}
2117
2118/**
Yong Li51709ff2019-09-30 14:13:04 +08002119 * @brief Translates watchdog timeout action DBUS property value to redfish.
2120 *
2121 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2122 *
2123 * @return Returns as a string, the timeout action in Redfish terms. If
2124 * translation cannot be done, returns an empty string.
2125 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002126inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002127{
2128 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2129 {
2130 return "None";
2131 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002132 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002133 {
2134 return "ResetSystem";
2135 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002136 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002137 {
2138 return "PowerDown";
2139 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002140 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002141 {
2142 return "PowerCycle";
2143 }
2144
2145 return "";
2146}
2147
2148/**
Yong Lic45f0082019-10-10 14:19:01 +08002149 *@brief Translates timeout action from Redfish to DBUS property value.
2150 *
2151 *@param[in] rfAction The timeout action in Redfish.
2152 *
2153 *@return Returns as a string, the time_out action as expected by DBUS.
2154 *If translation cannot be done, returns an empty string.
2155 */
2156
Ed Tanous23a21a12020-07-25 04:45:05 +00002157inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002158{
2159 if (rfAction == "None")
2160 {
2161 return "xyz.openbmc_project.State.Watchdog.Action.None";
2162 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002163 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002164 {
2165 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2166 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002167 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002168 {
2169 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2170 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002171 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002172 {
2173 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2174 }
2175
2176 return "";
2177}
2178
2179/**
Yong Li51709ff2019-09-30 14:13:04 +08002180 * @brief Retrieves host watchdog timer properties over DBUS
2181 *
2182 * @param[in] aResp Shared pointer for completing asynchronous calls.
2183 *
2184 * @return None.
2185 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002186inline void
2187 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002188{
2189 BMCWEB_LOG_DEBUG << "Get host watchodg";
2190 crow::connections::systemBus->async_method_call(
2191 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002192 const dbus::utility::DBusPropertiesMap& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002193 if (ec)
2194 {
2195 // watchdog service is stopped
2196 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2197 return;
2198 }
2199
2200 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2201
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002202 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002203 aResp->res.jsonValue["HostWatchdogTimer"];
2204
2205 // watchdog service is running/enabled
2206 hostWatchdogTimer["Status"]["State"] = "Enabled";
2207
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002208 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002209 {
2210 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2211 if (property.first == "Enabled")
2212 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002213 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002214
Ed Tanouse662eae2022-01-25 10:39:19 -08002215 if (state == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002216 {
2217 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002218 return;
Yong Li51709ff2019-09-30 14:13:04 +08002219 }
2220
2221 hostWatchdogTimer["FunctionEnabled"] = *state;
2222 }
2223 else if (property.first == "ExpireAction")
2224 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002225 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002226 std::get_if<std::string>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002227 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002228 {
2229 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002230 return;
Yong Li51709ff2019-09-30 14:13:04 +08002231 }
2232
2233 std::string action = dbusToRfWatchdogAction(*s);
2234 if (action.empty())
2235 {
2236 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002237 return;
Yong Li51709ff2019-09-30 14:13:04 +08002238 }
2239 hostWatchdogTimer["TimeoutAction"] = action;
2240 }
2241 }
2242 },
2243 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2244 "org.freedesktop.DBus.Properties", "GetAll",
2245 "xyz.openbmc_project.State.Watchdog");
2246}
2247
2248/**
Yong Lic45f0082019-10-10 14:19:01 +08002249 * @brief Sets Host WatchDog Timer properties.
2250 *
2251 * @param[in] aResp Shared pointer for generating response message.
2252 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2253 * RF request.
2254 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2255 *
2256 * @return None.
2257 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002258inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002259 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002260 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002261{
2262 BMCWEB_LOG_DEBUG << "Set host watchdog";
2263
2264 if (wdtTimeOutAction)
2265 {
2266 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2267 // check if TimeOut Action is Valid
2268 if (wdtTimeOutActStr.empty())
2269 {
2270 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2271 << *wdtTimeOutAction;
2272 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2273 "TimeoutAction");
2274 return;
2275 }
2276
2277 crow::connections::systemBus->async_method_call(
2278 [aResp](const boost::system::error_code ec) {
2279 if (ec)
2280 {
2281 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2282 messages::internalError(aResp->res);
2283 return;
2284 }
2285 },
2286 "xyz.openbmc_project.Watchdog",
2287 "/xyz/openbmc_project/watchdog/host0",
2288 "org.freedesktop.DBus.Properties", "Set",
2289 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002290 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002291 }
2292
2293 if (wdtEnable)
2294 {
2295 crow::connections::systemBus->async_method_call(
2296 [aResp](const boost::system::error_code ec) {
2297 if (ec)
2298 {
2299 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2300 messages::internalError(aResp->res);
2301 return;
2302 }
2303 },
2304 "xyz.openbmc_project.Watchdog",
2305 "/xyz/openbmc_project/watchdog/host0",
2306 "org.freedesktop.DBus.Properties", "Set",
2307 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002308 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002309 }
2310}
2311
Chris Cain37bbf982021-09-20 10:53:09 -05002312using ipsPropertiesType =
2313 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2314/**
2315 * @brief Parse the Idle Power Saver properties into json
2316 *
2317 * @param[in] aResp Shared pointer for completing asynchronous calls.
2318 * @param[in] properties IPS property data from DBus.
2319 *
2320 * @return true if successful
2321 */
Ed Tanousf6674222021-11-13 09:41:41 -08002322inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2323 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002324{
2325 for (const auto& property : properties)
2326 {
2327 if (property.first == "Enabled")
2328 {
2329 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002330 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002331 {
2332 return false;
2333 }
2334 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2335 }
2336 else if (property.first == "EnterUtilizationPercent")
2337 {
2338 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002339 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002340 {
2341 return false;
2342 }
2343 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2344 }
2345 else if (property.first == "EnterDwellTime")
2346 {
2347 // Convert Dbus time from milliseconds to seconds
2348 const uint64_t* timeMilliseconds =
2349 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002350 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002351 {
2352 return false;
2353 }
2354 const std::chrono::duration<uint64_t, std::milli> ms(
2355 *timeMilliseconds);
2356 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2357 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2358 .count();
2359 }
2360 else if (property.first == "ExitUtilizationPercent")
2361 {
2362 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002363 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002364 {
2365 return false;
2366 }
2367 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2368 }
2369 else if (property.first == "ExitDwellTime")
2370 {
2371 // Convert Dbus time from milliseconds to seconds
2372 const uint64_t* timeMilliseconds =
2373 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002374 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002375 {
2376 return false;
2377 }
2378 const std::chrono::duration<uint64_t, std::milli> ms(
2379 *timeMilliseconds);
2380 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2381 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2382 .count();
2383 }
2384 else
2385 {
2386 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2387 << property.first;
2388 }
2389 }
2390
2391 return true;
2392}
2393
2394/**
2395 * @brief Retrieves host watchdog timer properties over DBUS
2396 *
2397 * @param[in] aResp Shared pointer for completing asynchronous calls.
2398 *
2399 * @return None.
2400 */
2401inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2402{
2403 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2404
2405 // Get IdlePowerSaver object path:
2406 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002407 [aResp](const boost::system::error_code ec,
2408 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain37bbf982021-09-20 10:53:09 -05002409 if (ec)
2410 {
2411 BMCWEB_LOG_DEBUG
2412 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2413 << ec;
2414 messages::internalError(aResp->res);
2415 return;
2416 }
2417 if (subtree.empty())
2418 {
2419 // This is an optional interface so just return
2420 // if there is no instance found
2421 BMCWEB_LOG_DEBUG << "No instances found";
2422 return;
2423 }
2424 if (subtree.size() > 1)
2425 {
2426 // More then one PowerIdlePowerSaver object is not supported and
2427 // is an error
2428 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2429 "Power.IdlePowerSaver objects: "
2430 << subtree.size();
2431 messages::internalError(aResp->res);
2432 return;
2433 }
2434 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2435 {
2436 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2437 messages::internalError(aResp->res);
2438 return;
2439 }
2440 const std::string& path = subtree[0].first;
2441 const std::string& service = subtree[0].second.begin()->first;
2442 if (service.empty())
2443 {
2444 BMCWEB_LOG_DEBUG
2445 << "Power.IdlePowerSaver service mapper error!";
2446 messages::internalError(aResp->res);
2447 return;
2448 }
2449
2450 // Valid IdlePowerSaver object found, now read the current values
2451 crow::connections::systemBus->async_method_call(
2452 [aResp](const boost::system::error_code ec,
2453 ipsPropertiesType& properties) {
2454 if (ec)
2455 {
2456 BMCWEB_LOG_ERROR
2457 << "DBUS response error on IdlePowerSaver GetAll: "
2458 << ec;
2459 messages::internalError(aResp->res);
2460 return;
2461 }
2462
Ed Tanouse05aec52022-01-25 10:28:56 -08002463 if (!parseIpsProperties(aResp, properties))
Chris Cain37bbf982021-09-20 10:53:09 -05002464 {
2465 messages::internalError(aResp->res);
2466 return;
2467 }
2468 },
2469 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2470 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2471 },
2472 "xyz.openbmc_project.ObjectMapper",
2473 "/xyz/openbmc_project/object_mapper",
2474 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2475 std::array<const char*, 1>{
2476 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2477
2478 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2479}
2480
2481/**
2482 * @brief Sets Idle Power Saver properties.
2483 *
2484 * @param[in] aResp Shared pointer for generating response message.
2485 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2486 * RF request.
2487 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2488 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2489 * before entering idle state.
2490 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2491 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2492 * before exiting idle state
2493 *
2494 * @return None.
2495 */
2496inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2497 const std::optional<bool> ipsEnable,
2498 const std::optional<uint8_t> ipsEnterUtil,
2499 const std::optional<uint64_t> ipsEnterTime,
2500 const std::optional<uint8_t> ipsExitUtil,
2501 const std::optional<uint64_t> ipsExitTime)
2502{
2503 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2504
2505 // Get IdlePowerSaver object path:
2506 crow::connections::systemBus->async_method_call(
2507 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002508 ipsExitTime](const boost::system::error_code ec,
2509 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain37bbf982021-09-20 10:53:09 -05002510 if (ec)
2511 {
2512 BMCWEB_LOG_DEBUG
2513 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2514 << ec;
2515 messages::internalError(aResp->res);
2516 return;
2517 }
2518 if (subtree.empty())
2519 {
2520 // This is an optional D-Bus object, but user attempted to patch
2521 messages::resourceNotFound(aResp->res, "ComputerSystem",
2522 "IdlePowerSaver");
2523 return;
2524 }
2525 if (subtree.size() > 1)
2526 {
2527 // More then one PowerIdlePowerSaver object is not supported and
2528 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002529 BMCWEB_LOG_DEBUG
2530 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2531 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002532 messages::internalError(aResp->res);
2533 return;
2534 }
2535 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2536 {
2537 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2538 messages::internalError(aResp->res);
2539 return;
2540 }
2541 const std::string& path = subtree[0].first;
2542 const std::string& service = subtree[0].second.begin()->first;
2543 if (service.empty())
2544 {
2545 BMCWEB_LOG_DEBUG
2546 << "Power.IdlePowerSaver service mapper error!";
2547 messages::internalError(aResp->res);
2548 return;
2549 }
2550
2551 // Valid Power IdlePowerSaver object found, now set any values that
2552 // need to be updated
2553
2554 if (ipsEnable)
2555 {
2556 crow::connections::systemBus->async_method_call(
2557 [aResp](const boost::system::error_code ec) {
2558 if (ec)
2559 {
2560 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2561 messages::internalError(aResp->res);
2562 return;
2563 }
2564 },
2565 service, path, "org.freedesktop.DBus.Properties", "Set",
2566 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002567 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002568 }
2569 if (ipsEnterUtil)
2570 {
2571 crow::connections::systemBus->async_method_call(
2572 [aResp](const boost::system::error_code ec) {
2573 if (ec)
2574 {
2575 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2576 messages::internalError(aResp->res);
2577 return;
2578 }
2579 },
2580 service, path, "org.freedesktop.DBus.Properties", "Set",
2581 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2582 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002583 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002584 }
2585 if (ipsEnterTime)
2586 {
2587 // Convert from seconds into milliseconds for DBus
2588 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2589 crow::connections::systemBus->async_method_call(
2590 [aResp](const boost::system::error_code ec) {
2591 if (ec)
2592 {
2593 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2594 messages::internalError(aResp->res);
2595 return;
2596 }
2597 },
2598 service, path, "org.freedesktop.DBus.Properties", "Set",
2599 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002600 "EnterDwellTime",
2601 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002602 }
2603 if (ipsExitUtil)
2604 {
2605 crow::connections::systemBus->async_method_call(
2606 [aResp](const boost::system::error_code ec) {
2607 if (ec)
2608 {
2609 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2610 messages::internalError(aResp->res);
2611 return;
2612 }
2613 },
2614 service, path, "org.freedesktop.DBus.Properties", "Set",
2615 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2616 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002617 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002618 }
2619 if (ipsExitTime)
2620 {
2621 // Convert from seconds into milliseconds for DBus
2622 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2623 crow::connections::systemBus->async_method_call(
2624 [aResp](const boost::system::error_code ec) {
2625 if (ec)
2626 {
2627 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2628 messages::internalError(aResp->res);
2629 return;
2630 }
2631 },
2632 service, path, "org.freedesktop.DBus.Properties", "Set",
2633 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002634 "ExitDwellTime",
2635 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002636 }
2637 },
2638 "xyz.openbmc_project.ObjectMapper",
2639 "/xyz/openbmc_project/object_mapper",
2640 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2641 std::array<const char*, 1>{
2642 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2643
2644 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2645}
2646
Yong Lic45f0082019-10-10 14:19:01 +08002647/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002648 * SystemsCollection derived class for delivering ComputerSystems Collection
2649 * Schema
2650 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002651inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002652{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002653 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002654 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002655 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002656 [&app](const crow::Request& req,
2657 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2658 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2659 {
2660 return;
2661 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002662 asyncResp->res.jsonValue["@odata.type"] =
2663 "#ComputerSystemCollection.ComputerSystemCollection";
2664 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2665 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002666
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002667 sdbusplus::asio::getProperty<std::string>(
2668 *crow::connections::systemBus,
2669 "xyz.openbmc_project.Settings",
2670 "/xyz/openbmc_project/network/hypervisor",
2671 "xyz.openbmc_project.Network.SystemConfiguration",
2672 "HostName",
2673 [asyncResp](const boost::system::error_code ec,
2674 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002675 nlohmann::json& ifaceArray =
2676 asyncResp->res.jsonValue["Members"];
2677 ifaceArray = nlohmann::json::array();
2678 auto& count =
2679 asyncResp->res.jsonValue["Members@odata.count"];
2680 ifaceArray.push_back(
2681 {{"@odata.id", "/redfish/v1/Systems/system"}});
2682 count = ifaceArray.size();
2683 if (!ec)
2684 {
2685 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2686 ifaceArray.push_back(
2687 {{"@odata.id",
2688 "/redfish/v1/Systems/hypervisor"}});
2689 count = ifaceArray.size();
2690 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002691 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002692 });
2693}
Sunitha Harish462023a2020-02-19 08:34:59 -06002694
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002695/**
2696 * Function transceives data with dbus directly.
2697 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002698inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002699{
2700 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2701 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2702 constexpr char const* interfaceName =
2703 "xyz.openbmc_project.Control.Host.NMI";
2704 constexpr char const* method = "NMI";
2705
2706 crow::connections::systemBus->async_method_call(
2707 [asyncResp](const boost::system::error_code ec) {
2708 if (ec)
2709 {
2710 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2711 messages::internalError(asyncResp->res);
2712 return;
2713 }
2714 messages::success(asyncResp->res);
2715 },
2716 serviceName, objectPath, interfaceName, method);
2717}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002718
2719/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002720 * SystemActionsReset class supports handle POST method for Reset action.
2721 * The class retrieves and sends data directly to D-Bus.
2722 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002723inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002724{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002725 /**
2726 * Function handles POST method request.
2727 * Analyzes POST body message before sends Reset request data to D-Bus.
2728 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002729 BMCWEB_ROUTE(app,
2730 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002731 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002732 .methods(
2733 boost::beast::http::verb::
2734 post)([](const crow::Request& req,
2735 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2736 std::string resetType;
Willy Tu15ed6782021-12-14 11:03:16 -08002737 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2738 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002739 {
2740 return;
2741 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002742
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002743 // Get the command and host vs. chassis
2744 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002745 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002746 if ((resetType == "On") || (resetType == "ForceOn"))
2747 {
2748 command = "xyz.openbmc_project.State.Host.Transition.On";
2749 hostCommand = true;
2750 }
2751 else if (resetType == "ForceOff")
2752 {
2753 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2754 hostCommand = false;
2755 }
2756 else if (resetType == "ForceRestart")
2757 {
2758 command =
2759 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2760 hostCommand = true;
2761 }
2762 else if (resetType == "GracefulShutdown")
2763 {
2764 command = "xyz.openbmc_project.State.Host.Transition.Off";
2765 hostCommand = true;
2766 }
2767 else if (resetType == "GracefulRestart")
2768 {
George Liu0fda0f12021-11-16 10:06:17 +08002769 command =
2770 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002771 hostCommand = true;
2772 }
2773 else if (resetType == "PowerCycle")
2774 {
2775 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2776 hostCommand = true;
2777 }
2778 else if (resetType == "Nmi")
2779 {
2780 doNMI(asyncResp);
2781 return;
2782 }
2783 else
2784 {
2785 messages::actionParameterUnknown(asyncResp->res, "Reset",
2786 resetType);
2787 return;
2788 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002789
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002790 if (hostCommand)
2791 {
2792 crow::connections::systemBus->async_method_call(
2793 [asyncResp, resetType](const boost::system::error_code ec) {
2794 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002795 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002796 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2797 if (ec.value() ==
2798 boost::asio::error::invalid_argument)
2799 {
2800 messages::actionParameterNotSupported(
2801 asyncResp->res, resetType, "Reset");
2802 }
2803 else
2804 {
2805 messages::internalError(asyncResp->res);
2806 }
2807 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002808 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002809 messages::success(asyncResp->res);
2810 },
2811 "xyz.openbmc_project.State.Host",
2812 "/xyz/openbmc_project/state/host0",
2813 "org.freedesktop.DBus.Properties", "Set",
2814 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002815 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002816 }
2817 else
2818 {
2819 crow::connections::systemBus->async_method_call(
2820 [asyncResp, resetType](const boost::system::error_code ec) {
2821 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002822 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002823 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2824 if (ec.value() ==
2825 boost::asio::error::invalid_argument)
2826 {
2827 messages::actionParameterNotSupported(
2828 asyncResp->res, resetType, "Reset");
2829 }
2830 else
2831 {
2832 messages::internalError(asyncResp->res);
2833 }
2834 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002835 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002836 messages::success(asyncResp->res);
2837 },
2838 "xyz.openbmc_project.State.Chassis",
2839 "/xyz/openbmc_project/state/chassis0",
2840 "org.freedesktop.DBus.Properties", "Set",
2841 "xyz.openbmc_project.State.Chassis",
2842 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002843 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002844 }
2845 });
2846}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002847
2848/**
Ed Tanous66173382018-08-15 18:20:59 -07002849 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002850 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002851inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002852{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002853
Ed Tanous1abe55e2018-09-05 08:30:59 -07002854 /**
2855 * Functions triggers appropriate requests on DBus
2856 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002857 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002858 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002859 .methods(
2860 boost::beast::http::verb::
2861 get)([](const crow::Request&,
2862 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2863 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002864 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002865 asyncResp->res.jsonValue["Name"] = "system";
2866 asyncResp->res.jsonValue["Id"] = "system";
2867 asyncResp->res.jsonValue["SystemType"] = "Physical";
2868 asyncResp->res.jsonValue["Description"] = "Computer System";
2869 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2870 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2871 "Disabled";
2872 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2873 uint64_t(0);
2874 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2875 "Disabled";
2876 asyncResp->res.jsonValue["@odata.id"] =
2877 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002878
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002879 asyncResp->res.jsonValue["Processors"] = {
2880 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2881 asyncResp->res.jsonValue["Memory"] = {
2882 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2883 asyncResp->res.jsonValue["Storage"] = {
2884 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002885
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002886 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2887 {"target",
2888 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2889 {"@Redfish.ActionInfo",
2890 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002891
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002892 asyncResp->res.jsonValue["LogServices"] = {
2893 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002894
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002895 asyncResp->res.jsonValue["Bios"] = {
2896 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002897
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002898 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2899 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002900
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002901 asyncResp->res.jsonValue["Status"] = {
2902 {"Health", "OK"},
2903 {"State", "Enabled"},
2904 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002905
2906 // Fill in SerialConsole info
2907 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2908 15;
2909 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2910 {"ServiceEnabled", true},
2911 };
2912 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2913 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2914 {"ServiceEnabled", true},
2915 {"Port", 2200},
2916 // https://github.com/openbmc/docs/blob/master/console.md
2917 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2918 };
2919
2920#ifdef BMCWEB_ENABLE_KVM
2921 // Fill in GraphicalConsole info
2922 asyncResp->res.jsonValue["GraphicalConsole"] = {
2923 {"ServiceEnabled", true},
2924 {"MaxConcurrentSessions", 4},
2925 {"ConnectTypesSupported", {"KVMIP"}},
2926 };
2927#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002928 constexpr const std::array<const char*, 4> inventoryForSystems = {
2929 "xyz.openbmc_project.Inventory.Item.Dimm",
2930 "xyz.openbmc_project.Inventory.Item.Cpu",
2931 "xyz.openbmc_project.Inventory.Item.Drive",
2932 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002933
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002934 auto health = std::make_shared<HealthPopulate>(asyncResp);
2935 crow::connections::systemBus->async_method_call(
2936 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002937 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002938 if (ec)
2939 {
2940 // no inventory
2941 return;
2942 }
2943
Ed Tanous914e2d52022-01-07 11:38:34 -08002944 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002945 },
2946 "xyz.openbmc_project.ObjectMapper",
2947 "/xyz/openbmc_project/object_mapper",
2948 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2949 int32_t(0), inventoryForSystems);
2950
2951 health->populate();
2952
2953 getMainChassisId(
2954 asyncResp, [](const std::string& chassisId,
2955 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2956 aRsp->res.jsonValue["Links"]["Chassis"] = {
2957 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2958 });
2959
2960 getLocationIndicatorActive(asyncResp);
2961 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2962 getIndicatorLedState(asyncResp);
2963 getComputerSystem(asyncResp, health);
2964 getHostState(asyncResp);
2965 getBootProperties(asyncResp);
2966 getBootProgress(asyncResp);
2967 getPCIeDeviceList(asyncResp, "PCIeDevices");
2968 getHostWatchdogTimer(asyncResp);
2969 getPowerRestorePolicy(asyncResp);
2970 getAutomaticRetry(asyncResp);
2971 getLastResetTime(asyncResp);
2972#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2973 getProvisioningStatus(asyncResp);
2974#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002975 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002976 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05002977 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002978 });
2979 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002980 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002981 .methods(boost::beast::http::verb::patch)(
2982 [](const crow::Request& req,
2983 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2984 std::optional<bool> locationIndicatorActive;
2985 std::optional<std::string> indicatorLed;
2986 std::optional<nlohmann::json> bootProps;
2987 std::optional<nlohmann::json> wdtTimerProps;
2988 std::optional<std::string> assetTag;
2989 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002990 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05002991 std::optional<nlohmann::json> ipsProps;
Willy Tu15ed6782021-12-14 11:03:16 -08002992 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002993 req, asyncResp->res, "IndicatorLED", indicatorLed,
2994 "LocationIndicatorActive", locationIndicatorActive,
2995 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2996 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05002997 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
2998 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07002999 {
James Feistb49ac872019-05-21 15:12:01 -07003000 return;
3001 }
3002
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003003 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003004
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003005 if (assetTag)
3006 {
3007 setAssetTag(asyncResp, *assetTag);
3008 }
James Feistb49ac872019-05-21 15:12:01 -07003009
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003010 if (wdtTimerProps)
3011 {
3012 std::optional<bool> wdtEnable;
3013 std::optional<std::string> wdtTimeOutAction;
3014
3015 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3016 "FunctionEnabled", wdtEnable,
3017 "TimeoutAction", wdtTimeOutAction))
3018 {
3019 return;
3020 }
3021 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3022 }
3023
3024 if (bootProps)
3025 {
3026 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003027 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003028 std::optional<std::string> bootEnable;
3029 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003030 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003031
3032 if (!json_util::readJson(
3033 *bootProps, asyncResp->res,
3034 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003035 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003036 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003037 "AutomaticRetryConfig", automaticRetryConfig,
3038 "TrustedModuleRequiredToBoot",
3039 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003040 {
3041 return;
3042 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003043
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003044 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003045 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003046 setBootProperties(asyncResp, bootSource, bootType,
3047 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003048 }
3049 if (automaticRetryConfig)
3050 {
3051 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3052 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003053
3054 if (trustedModuleRequiredToBoot)
3055 {
3056 setTrustedModuleRequiredToBoot(
3057 asyncResp, *trustedModuleRequiredToBoot);
3058 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003059 }
3060
3061 if (locationIndicatorActive)
3062 {
3063 setLocationIndicatorActive(asyncResp,
3064 *locationIndicatorActive);
3065 }
3066
3067 // TODO (Gunnar): Remove IndicatorLED after enough time has
3068 // passed
3069 if (indicatorLed)
3070 {
3071 setIndicatorLedState(asyncResp, *indicatorLed);
3072 asyncResp->res.addHeader(
3073 boost::beast::http::field::warning,
3074 "299 - \"IndicatorLED is deprecated. Use "
3075 "LocationIndicatorActive instead.\"");
3076 }
3077
3078 if (powerRestorePolicy)
3079 {
3080 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3081 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003082
3083 if (powerMode)
3084 {
3085 setPowerMode(asyncResp, *powerMode);
3086 }
Chris Cain37bbf982021-09-20 10:53:09 -05003087
3088 if (ipsProps)
3089 {
3090 std::optional<bool> ipsEnable;
3091 std::optional<uint8_t> ipsEnterUtil;
3092 std::optional<uint64_t> ipsEnterTime;
3093 std::optional<uint8_t> ipsExitUtil;
3094 std::optional<uint64_t> ipsExitTime;
3095
3096 if (!json_util::readJson(
3097 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3098 "EnterUtilizationPercent", ipsEnterUtil,
3099 "EnterDwellTimeSeconds", ipsEnterTime,
3100 "ExitUtilizationPercent", ipsExitUtil,
3101 "ExitDwellTimeSeconds", ipsExitTime))
3102 {
3103 return;
3104 }
3105 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3106 ipsEnterTime, ipsExitUtil, ipsExitTime);
3107 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003108 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003109}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303110
3111/**
3112 * SystemResetActionInfo derived class for delivering Computer Systems
3113 * ResetType AllowableValues using ResetInfo schema.
3114 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003115inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303116{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303117
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303118 /**
3119 * Functions triggers appropriate requests on DBus
3120 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003121 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003122 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003123 .methods(boost::beast::http::verb::get)(
3124 [](const crow::Request&,
3125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3126 asyncResp->res.jsonValue = {
3127 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3128 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3129 {"Name", "Reset Action Info"},
3130 {"Id", "ResetActionInfo"},
3131 {"Parameters",
3132 {{{"Name", "ResetType"},
3133 {"Required", true},
3134 {"DataType", "String"},
3135 {"AllowableValues",
3136 {"On", "ForceOff", "ForceOn", "ForceRestart",
3137 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3138 "Nmi"}}}}}};
3139 });
3140}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003141} // namespace redfish