blob: 429e99242c376fa28cce0c089ab85cd73bb3c7a0 [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"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
23
John Edward Broadbent7e860f12021-04-08 15:57:16 -070024#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070025#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080026#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070027#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070028#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060029#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050031
Ed Tanousabf2add2019-01-22 16:40:12 -080032#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034namespace redfish
35{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020036
Alpana Kumari9d3ae102019-04-12 06:49:32 -050037/**
38 * @brief Updates the Functional State of DIMMs
39 *
40 * @param[in] aResp Shared pointer for completing asynchronous calls
41 * @param[in] dimmState Dimm's Functional state, true/false
42 *
43 * @return None.
44 */
zhanghch058d1b46d2021-04-01 11:18:24 +080045inline void
46 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070047 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070049 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050
Gunnar Mills4e0453b2020-07-08 14:00:30 -050051 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052 // Update STATE only if previous State was DISABLED and current Dimm is
53 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050054 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
56 if (prevMemSummary == "Disabled")
57 {
Ed Tanouse05aec52022-01-25 10:28:56 -080058 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 {
60 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
61 "Enabled";
62 }
63 }
64}
65
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050066/*
67 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
68 *
69 * @param[in] aResp Shared pointer for completing asynchronous calls
70 * @param[in] cpuPresenceState CPU present or not
71 *
72 * @return None.
73 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074inline void
75 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
76 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070078 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079
Ed Tanous55f79e62022-01-25 11:26:16 -080080 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050082 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080083 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080084 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050085 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080086 if (procCountPtr != nullptr)
87 {
88 // shouldn't be possible to be nullptr
89 *procCountPtr += 1;
90 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092}
93
94/*
95 * @brief Update "ProcessorSummary" "Status" "State" based on
96 * CPU Functional State
97 *
98 * @param[in] aResp Shared pointer for completing asynchronous calls
99 * @param[in] cpuFunctionalState is CPU functional true/false
100 *
101 * @return None.
102 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700103inline void
104 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
105 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700107 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
111
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500112 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113 // Update STATE only if previous State was Non_Functional and current CPU is
114 // Functional.
115 if (prevProcState == "Disabled")
116 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800117 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 {
119 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
120 "Enabled";
121 }
122 }
123}
124
Ed Tanousb9d36b42022-02-26 21:42:46 -0800125inline void
126 getProcessorProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
127 const std::string& service, const std::string& path,
128 const dbus::utility::DBusPropertiesMap& properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500129{
130
131 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
132
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700133 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
134 const bool cpuPresenceCheck) {
135 if (ec3)
136 {
137 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
138 return;
139 }
140 modifyCpuPresenceState(aResp, cpuPresenceCheck);
141 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500142
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700143 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
144 const bool cpuFunctionalCheck) {
145 if (ec3)
146 {
147 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
148 return;
149 }
150 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
151 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500152
153 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700154 sdbusplus::asio::getProperty<bool>(
155 *crow::connections::systemBus, service, path,
156 "xyz.openbmc_project.Inventory.Item", "Present",
157 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500158
159 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700160 sdbusplus::asio::getProperty<bool>(
161 *crow::connections::systemBus, service, path,
162 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
163 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500164
165 for (const auto& property : properties)
166 {
167
168 // TODO: Get Model
169
170 // Get CoreCount
171 if (property.first == "CoreCount")
172 {
173
174 // Get CPU CoreCount and add it to the total
175 const uint16_t* coreCountVal =
176 std::get_if<uint16_t>(&property.second);
177
Ed Tanouse662eae2022-01-25 10:39:19 -0800178 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500179 {
180 messages::internalError(aResp->res);
181 return;
182 }
183
184 nlohmann::json& coreCount =
185 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
186 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
187
188 if (coreCountPtr == nullptr)
189 {
190 coreCount = 0;
191 }
192 else
193 {
194 *coreCountPtr += *coreCountVal;
195 }
196 }
197 }
198}
199
200/*
201 * @brief Get ProcessorSummary fields
202 *
203 * @param[in] aResp Shared pointer for completing asynchronous calls
204 * @param[in] service dbus service for Cpu Information
205 * @param[in] path dbus path for Cpu
206 *
207 * @return None.
208 */
209inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
210 const std::string& service,
211 const std::string& path)
212{
213
214 crow::connections::systemBus->async_method_call(
215 [aResp, service,
216 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800217 const dbus::utility::DBusPropertiesMap& properties) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500218 if (ec2)
219 {
220 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
221 messages::internalError(aResp->res);
222 return;
223 }
224 getProcessorProperties(aResp, service, path, properties);
225 },
226 service, path, "org.freedesktop.DBus.Properties", "GetAll",
227 "xyz.openbmc_project.Inventory.Item.Cpu");
228}
229
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500230/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700231 * @brief Retrieves computer system properties over dbus
232 *
233 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500234 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700235 *
236 * @return None.
237 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700238inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800239 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700240 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700241{
Ed Tanous6c34de42018-08-29 13:37:36 -0700242 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500243
Ed Tanous6c34de42018-08-29 13:37:36 -0700244 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800245 [aResp,
246 systemHealth](const boost::system::error_code ec,
247 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700248 if (ec)
249 {
250 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700251 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700252 return;
253 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700254 // Iterate over all retrieved ObjectPaths.
255 for (const std::pair<std::string,
256 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500257 std::string, std::vector<std::string>>>>&
258 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700259 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500260 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700261 BMCWEB_LOG_DEBUG << "Got path: " << path;
262 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500263 std::pair<std::string, std::vector<std::string>>>&
264 connectionNames = object.second;
Ed Tanous26f69762022-01-25 09:49:11 -0800265 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 {
267 continue;
268 }
Ed Tanous029573d2019-02-01 10:57:49 -0800269
James Feist5bc2dc82019-10-22 14:33:16 -0700270 auto memoryHealth = std::make_shared<HealthPopulate>(
271 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
272
273 auto cpuHealth = std::make_shared<HealthPopulate>(
274 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
275
276 systemHealth->children.emplace_back(memoryHealth);
277 systemHealth->children.emplace_back(cpuHealth);
278
Ed Tanous029573d2019-02-01 10:57:49 -0800279 // This is not system, so check if it's cpu, dimm, UUID or
280 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500281 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700282 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500283 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700284 {
Ed Tanous029573d2019-02-01 10:57:49 -0800285 if (interfaceName ==
286 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700287 {
Ed Tanous029573d2019-02-01 10:57:49 -0800288 BMCWEB_LOG_DEBUG
289 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500290
Ed Tanous029573d2019-02-01 10:57:49 -0800291 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500292 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700293 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800294 const dbus::utility::DBusPropertiesMap&
Ed Tanousf23b7292020-10-15 09:41:17 -0700295 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000296 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800297 {
298 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000299 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800300 messages::internalError(aResp->res);
301 return;
302 }
303 BMCWEB_LOG_DEBUG << "Got "
304 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500305 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500306
Ed Tanous26f69762022-01-25 09:49:11 -0800307 if (!properties.empty())
Ed Tanous029573d2019-02-01 10:57:49 -0800308 {
Ed Tanous168e20c2021-12-13 14:39:53 -0800309 for (const std::pair<
310 std::string,
311 dbus::utility::
312 DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500313 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700314 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800315 if (property.first !=
316 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700317 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800318 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700319 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500321 std::get_if<uint32_t>(
322 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800323 if (value == nullptr)
324 {
325 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800326 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800327 continue;
328 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500329 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800330 aResp->res.jsonValue
331 ["MemorySummary"]
332 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500333 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800334 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500335 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800336 if (preValue == nullptr)
337 {
338 continue;
339 }
George Liu0fda0f12021-11-16 10:06:17 +0800340 aResp->res.jsonValue
341 ["MemorySummary"]
342 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800343 *value / (1024 * 1024) +
344 *preValue;
345 aResp->res
346 .jsonValue["MemorySummary"]
347 ["Status"]["State"] =
348 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700349 }
Ed Tanous029573d2019-02-01 10:57:49 -0800350 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500351 else
352 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700353 sdbusplus::asio::getProperty<bool>(
354 *crow::connections::systemBus,
355 service, path,
356 "xyz.openbmc_project.State."
357 "Decorator.OperationalStatus",
358 "Functional",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500359 [aResp](
360 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000361 ec3,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700362 bool dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000363 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500364 {
365 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800366 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000367 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500368 return;
369 }
370 updateDimmProperties(aResp,
371 dimmState);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700372 });
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500373 }
Ed Tanous029573d2019-02-01 10:57:49 -0800374 },
375 connection.first, path,
376 "org.freedesktop.DBus.Properties", "GetAll",
377 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700378
379 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800380 }
381 else if (interfaceName ==
382 "xyz.openbmc_project.Inventory.Item.Cpu")
383 {
384 BMCWEB_LOG_DEBUG
385 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500386
Ali Ahmed03fbed92021-09-03 02:33:43 -0500387 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700388
389 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800390 }
391 else if (interfaceName ==
392 "xyz.openbmc_project.Common.UUID")
393 {
394 BMCWEB_LOG_DEBUG
395 << "Found UUID, now get its properties.";
396 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800397 [aResp](const boost::system::error_code ec3,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800398 const dbus::utility::DBusPropertiesMap&
Ed Tanous168e20c2021-12-13 14:39:53 -0800399 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000400 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800401 {
402 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000403 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800404 messages::internalError(aResp->res);
405 return;
406 }
407 BMCWEB_LOG_DEBUG << "Got "
408 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500409 << " UUID properties.";
Ed Tanous168e20c2021-12-13 14:39:53 -0800410 for (const std::pair<
411 std::string,
412 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500413 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800414 {
Ed Tanous029573d2019-02-01 10:57:49 -0800415 if (property.first == "UUID")
416 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500417 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500418 std::get_if<std::string>(
419 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700420
Ed Tanous029573d2019-02-01 10:57:49 -0800421 if (value != nullptr)
422 {
423 std::string valueStr = *value;
424 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700425 {
Ed Tanous029573d2019-02-01 10:57:49 -0800426 valueStr.insert(8, 1, '-');
427 valueStr.insert(13, 1, '-');
428 valueStr.insert(18, 1, '-');
429 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700430 }
Ed Tanous029573d2019-02-01 10:57:49 -0800431 BMCWEB_LOG_DEBUG << "UUID = "
432 << valueStr;
433 aResp->res.jsonValue["UUID"] =
434 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700435 }
436 }
Ed Tanous029573d2019-02-01 10:57:49 -0800437 }
438 },
439 connection.first, path,
440 "org.freedesktop.DBus.Properties", "GetAll",
441 "xyz.openbmc_project.Common.UUID");
442 }
443 else if (interfaceName ==
444 "xyz.openbmc_project.Inventory.Item.System")
445 {
446 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800447 [aResp](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800448 const dbus::utility::DBusPropertiesMap&
Ed Tanous168e20c2021-12-13 14:39:53 -0800449 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000450 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800451 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700452 // doesn't have to include this
453 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800454 return;
455 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500456 BMCWEB_LOG_DEBUG
457 << "Got " << propertiesList.size()
458 << " properties for system";
Ed Tanous168e20c2021-12-13 14:39:53 -0800459 for (const std::pair<
460 std::string,
461 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500462 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800463 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500464 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600465 property.first;
466 if ((propertyName == "PartNumber") ||
467 (propertyName == "SerialNumber") ||
468 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500469 (propertyName == "Model") ||
470 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800471 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500472 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600473 std::get_if<std::string>(
474 &property.second);
475 if (value != nullptr)
476 {
477 aResp->res
478 .jsonValue[propertyName] =
479 *value;
480 }
Ed Tanous029573d2019-02-01 10:57:49 -0800481 }
482 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500483
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600484 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500485 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600486 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500487 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800488 },
489 connection.first, path,
490 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800491 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700492
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700493 sdbusplus::asio::getProperty<std::string>(
494 *crow::connections::systemBus, connection.first,
495 path,
496 "xyz.openbmc_project.Inventory.Decorator."
497 "AssetTag",
498 "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -0800499 [aResp](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700500 const std::string& value) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000501 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700502 {
503 // doesn't have to include this
504 // interface
505 return;
506 }
507
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700508 aResp->res.jsonValue["AssetTag"] = value;
509 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700510 }
511 }
512 }
513 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700514 },
515 "xyz.openbmc_project.ObjectMapper",
516 "/xyz/openbmc_project/object_mapper",
517 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700518 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500519 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700520 "xyz.openbmc_project.Inventory.Decorator.Asset",
521 "xyz.openbmc_project.Inventory.Item.Cpu",
522 "xyz.openbmc_project.Inventory.Item.Dimm",
523 "xyz.openbmc_project.Inventory.Item.System",
524 "xyz.openbmc_project.Common.UUID",
525 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700526}
527
528/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700529 * @brief Retrieves host state properties over dbus
530 *
531 * @param[in] aResp Shared pointer for completing asynchronous calls.
532 *
533 * @return None.
534 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800535inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700536{
537 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700538 sdbusplus::asio::getProperty<std::string>(
539 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
540 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
541 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800542 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700543 const std::string& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700544 if (ec)
545 {
Andrew Geissler22228c22022-01-31 13:55:33 -0600546 if (ec == boost::system::errc::host_unreachable)
547 {
548 // Service not available, no error, just don't return
549 // host state info
550 BMCWEB_LOG_DEBUG << "Service not available " << ec;
551 return;
552 }
553 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700554 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700555 return;
556 }
Ed Tanous66173382018-08-15 18:20:59 -0700557
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700558 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
559 // Verify Host State
560 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700561 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700562 aResp->res.jsonValue["PowerState"] = "On";
563 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700564 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700565 else if (hostState ==
566 "xyz.openbmc_project.State.Host.HostState.Quiesced")
567 {
568 aResp->res.jsonValue["PowerState"] = "On";
569 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
570 }
571 else if (hostState ==
572 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
573 {
574 aResp->res.jsonValue["PowerState"] = "On";
575 aResp->res.jsonValue["Status"]["State"] = "InTest";
576 }
577 else if (
578 hostState ==
579 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
580 {
581 aResp->res.jsonValue["PowerState"] = "PoweringOn";
582 aResp->res.jsonValue["Status"]["State"] = "Starting";
583 }
584 else if (
585 hostState ==
586 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
587 {
588 aResp->res.jsonValue["PowerState"] = "PoweringOff";
589 aResp->res.jsonValue["Status"]["State"] = "Disabled";
590 }
591 else
592 {
593 aResp->res.jsonValue["PowerState"] = "Off";
594 aResp->res.jsonValue["Status"]["State"] = "Disabled";
595 }
596 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700597}
598
599/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500600 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530601 *
602 * @param[in] dbusSource The boot source in DBUS speak.
603 *
604 * @return Returns as a string, the boot source in Redfish terms. If translation
605 * cannot be done, returns an empty string.
606 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000607inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530608{
609 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
610 {
611 return "None";
612 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700613 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530614 {
615 return "Hdd";
616 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700617 if (dbusSource ==
618 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530619 {
620 return "Cd";
621 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700622 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530623 {
624 return "Pxe";
625 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700626 if (dbusSource ==
627 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700628 {
629 return "Usb";
630 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700631 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530632}
633
634/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300635 * @brief Translates boot type DBUS property value to redfish.
636 *
637 * @param[in] dbusType The boot type in DBUS speak.
638 *
639 * @return Returns as a string, the boot type in Redfish terms. If translation
640 * cannot be done, returns an empty string.
641 */
642inline std::string dbusToRfBootType(const std::string& dbusType)
643{
644 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
645 {
646 return "Legacy";
647 }
648 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
649 {
650 return "UEFI";
651 }
652 return "";
653}
654
655/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500656 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530657 *
658 * @param[in] dbusMode The boot mode in DBUS speak.
659 *
660 * @return Returns as a string, the boot mode in Redfish terms. If translation
661 * cannot be done, returns an empty string.
662 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000663inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530664{
665 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
666 {
667 return "None";
668 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700669 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530670 {
671 return "Diags";
672 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700673 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674 {
675 return "BiosSetup";
676 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700677 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530678}
679
680/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600681 * @brief Translates boot progress DBUS property value to redfish.
682 *
683 * @param[in] dbusBootProgress The boot progress in DBUS speak.
684 *
685 * @return Returns as a string, the boot progress in Redfish terms. If
686 * translation cannot be done, returns "None".
687 */
688inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
689{
690 // Now convert the D-Bus BootProgress to the appropriate Redfish
691 // enum
692 std::string rfBpLastState = "None";
693 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
694 "ProgressStages.Unspecified")
695 {
696 rfBpLastState = "None";
697 }
698 else if (dbusBootProgress ==
699 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
700 "PrimaryProcInit")
701 {
702 rfBpLastState = "PrimaryProcessorInitializationStarted";
703 }
704 else if (dbusBootProgress ==
705 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
706 "BusInit")
707 {
708 rfBpLastState = "BusInitializationStarted";
709 }
710 else if (dbusBootProgress ==
711 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
712 "MemoryInit")
713 {
714 rfBpLastState = "MemoryInitializationStarted";
715 }
716 else if (dbusBootProgress ==
717 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
718 "SecondaryProcInit")
719 {
720 rfBpLastState = "SecondaryProcessorInitializationStarted";
721 }
722 else if (dbusBootProgress ==
723 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
724 "PCIInit")
725 {
726 rfBpLastState = "PCIResourceConfigStarted";
727 }
728 else if (dbusBootProgress ==
729 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
730 "SystemSetup")
731 {
732 rfBpLastState = "SetupEntered";
733 }
734 else if (dbusBootProgress ==
735 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
736 "SystemInitComplete")
737 {
738 rfBpLastState = "SystemHardwareInitializationComplete";
739 }
740 else if (dbusBootProgress ==
741 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
742 "OSStart")
743 {
744 rfBpLastState = "OSBootStarted";
745 }
746 else if (dbusBootProgress ==
747 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
748 "OSRunning")
749 {
750 rfBpLastState = "OSRunning";
751 }
752 else
753 {
754 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
755 << dbusBootProgress;
756 // Just return the default
757 }
758 return rfBpLastState;
759}
760
761/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500762 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530763 *
764 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700765 * @param[out] bootSource The DBus source
766 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530767 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700768 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530769 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800770inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500771 const std::string& rfSource,
772 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300774 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
775 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777 if (rfSource == "None")
778 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700781 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530782 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
784 }
785 else if (rfSource == "Hdd")
786 {
787 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
788 }
789 else if (rfSource == "Diags")
790 {
791 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
792 }
793 else if (rfSource == "Cd")
794 {
795 bootSource =
796 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
797 }
798 else if (rfSource == "BiosSetup")
799 {
800 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530801 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700802 else if (rfSource == "Usb")
803 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700804 bootSource =
805 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700806 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530807 else
808 {
George Liu0fda0f12021-11-16 10:06:17 +0800809 BMCWEB_LOG_DEBUG
810 << "Invalid property value for BootSourceOverrideTarget: "
811 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700812 messages::propertyValueNotInList(aResp->res, rfSource,
813 "BootSourceTargetOverride");
814 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530815 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700816 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530817}
Ali Ahmed19817712021-06-29 17:01:52 -0500818
Andrew Geissler978b8802020-11-19 13:36:40 -0600819/**
820 * @brief Retrieves boot progress of the system
821 *
822 * @param[in] aResp Shared pointer for generating response message.
823 *
824 * @return None.
825 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800826inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600827{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700828 sdbusplus::asio::getProperty<std::string>(
829 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
830 "/xyz/openbmc_project/state/host0",
831 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600832 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700833 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600834 if (ec)
835 {
836 // BootProgress is an optional object so just do nothing if
837 // not found
838 return;
839 }
840
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700841 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600842
Andrew Geisslere43914b2022-01-06 13:59:39 -0600843 aResp->res.jsonValue["BootProgress"]["LastState"] =
844 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700845 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600846}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530847
848/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300849 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300850 *
851 * @param[in] aResp Shared pointer for generating response message.
852 *
853 * @return None.
854 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300855
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300856inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300857{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700858 sdbusplus::asio::getProperty<std::string>(
859 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
860 "/xyz/openbmc_project/control/host0/boot",
861 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300862 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700863 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300864 if (ec)
865 {
866 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300867 return;
868 }
869
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700870 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300871
George Liu0fda0f12021-11-16 10:06:17 +0800872 aResp->res
873 .jsonValue["Boot"]
874 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
875 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300876
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700877 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300878 if (rfType.empty())
879 {
880 messages::internalError(aResp->res);
881 return;
882 }
883
884 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700885 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300886}
887
888/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300889 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530890 *
891 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530892 *
893 * @return None.
894 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300895
896inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530897{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700898 sdbusplus::asio::getProperty<std::string>(
899 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
900 "/xyz/openbmc_project/control/host0/boot",
901 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300902 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700903 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530904 if (ec)
905 {
906 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
907 messages::internalError(aResp->res);
908 return;
909 }
910
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700911 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530912
George Liu0fda0f12021-11-16 10:06:17 +0800913 aResp->res
914 .jsonValue["Boot"]
915 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
916 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530917
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700918 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530919 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
920 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700921 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530922 if (!rfMode.empty())
923 {
924 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
925 rfMode;
926 }
927 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700928 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530929}
930
931/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300932 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933 *
934 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530935 *
936 * @return None.
937 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300938
939inline void
940 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530941{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700942 sdbusplus::asio::getProperty<std::string>(
943 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
944 "/xyz/openbmc_project/control/host0/boot",
945 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300946 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700947 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530948 if (ec)
949 {
950 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
951 messages::internalError(aResp->res);
952 return;
953 }
954
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700955 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530956
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700957 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530958 if (!rfSource.empty())
959 {
960 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
961 rfSource;
962 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300963
964 // Get BootMode as BootSourceOverrideTarget is constructed
965 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300966 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700967 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530968}
969
970/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300971 * @brief This functions abstracts all the logic behind getting a
972 * "BootSourceOverrideEnabled" property from an overall boot override enable
973 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 *
975 * @param[in] aResp Shared pointer for generating response message.
976 *
977 * @return None.
978 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530979
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300980inline void
981 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
982 const bool bootOverrideEnableSetting)
983{
984 if (!bootOverrideEnableSetting)
985 {
986 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
987 return;
988 }
989
990 // If boot source override is enabled, we need to check 'one_time'
991 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700992 sdbusplus::asio::getProperty<bool>(
993 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
994 "/xyz/openbmc_project/control/host0/boot/one_time",
995 "xyz.openbmc_project.Object.Enable", "Enabled",
996 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530997 if (ec)
998 {
999 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001000 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301001 return;
1002 }
1003
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001004 if (oneTimeSetting)
1005 {
1006 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1007 "Once";
1008 }
1009 else
1010 {
1011 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1012 "Continuous";
1013 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001014 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301015}
1016
1017/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001018 * @brief Retrieves boot override enable over DBUS
1019 *
1020 * @param[in] aResp Shared pointer for generating response message.
1021 *
1022 * @return None.
1023 */
1024
1025inline void
1026 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1027{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001028 sdbusplus::asio::getProperty<bool>(
1029 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1030 "/xyz/openbmc_project/control/host0/boot",
1031 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001032 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001033 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001034 if (ec)
1035 {
1036 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1037 messages::internalError(aResp->res);
1038 return;
1039 }
1040
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001041 processBootOverrideEnable(aResp, bootOverrideEnable);
1042 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043}
1044
1045/**
1046 * @brief Retrieves boot source override properties
1047 *
1048 * @param[in] aResp Shared pointer for generating response message.
1049 *
1050 * @return None.
1051 */
1052inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1053{
1054 BMCWEB_LOG_DEBUG << "Get boot information.";
1055
1056 getBootOverrideSource(aResp);
1057 getBootOverrideType(aResp);
1058 getBootOverrideEnable(aResp);
1059}
1060
1061/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001062 * @brief Retrieves the Last Reset Time
1063 *
1064 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1065 * and power off. Even though this is the "system" Redfish object look at the
1066 * chassis D-Bus interface for the LastStateChangeTime since this has the
1067 * last power operation time.
1068 *
1069 * @param[in] aResp Shared pointer for generating response message.
1070 *
1071 * @return None.
1072 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001073inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001074{
1075 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1076
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001077 sdbusplus::asio::getProperty<uint64_t>(
1078 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1079 "/xyz/openbmc_project/state/chassis0",
1080 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1081 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001082 if (ec)
1083 {
1084 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1085 return;
1086 }
1087
Gunnar Millsc0557e12020-06-30 11:26:20 -05001088 // LastStateChangeTime is epoch time, in milliseconds
1089 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001090 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001091
1092 // Convert to ISO 8601 standard
1093 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001094 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001095 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001096}
1097
1098/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001099 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1100 *
1101 * @param[in] aResp Shared pointer for generating response message.
1102 *
1103 * @return None.
1104 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001105inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001106{
1107 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1108
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001109 sdbusplus::asio::getProperty<bool>(
1110 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1111 "/xyz/openbmc_project/control/host0/auto_reboot",
1112 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1113 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001114 if (ec)
1115 {
1116 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1117 return;
1118 }
1119
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001120 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
Ed Tanouse05aec52022-01-25 10:28:56 -08001121 if (autoRebootEnabled)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001122 {
1123 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1124 "RetryAttempts";
1125 // If AutomaticRetry (AutoReboot) is enabled see how many
1126 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001127 sdbusplus::asio::getProperty<uint32_t>(
1128 *crow::connections::systemBus,
1129 "xyz.openbmc_project.State.Host",
1130 "/xyz/openbmc_project/state/host0",
1131 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1132 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001133 [aResp](const boost::system::error_code ec2,
Ed Tanous914e2d52022-01-07 11:38:34 -08001134 const uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001135 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001136 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001137 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001138 return;
1139 }
1140
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001141 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001142 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001143
1144 aResp->res
1145 .jsonValue["Boot"]
1146 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001147 autoRebootAttemptsLeft;
1148 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001149 }
1150 else
1151 {
1152 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1153 "Disabled";
1154 }
1155
1156 // Not on D-Bus. Hardcoded here:
1157 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1158 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001159
1160 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1161 // and RetryAttempts. OpenBMC only supports Disabled and
1162 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001163 aResp->res
1164 .jsonValue["Boot"]
1165 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1166 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001167 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001168}
1169
1170/**
George Liuc6a620f2020-04-10 17:18:11 +08001171 * @brief Retrieves power restore policy over DBUS.
1172 *
1173 * @param[in] aResp Shared pointer for generating response message.
1174 *
1175 * @return None.
1176 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001177inline void
1178 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001179{
1180 BMCWEB_LOG_DEBUG << "Get power restore policy";
1181
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001182 sdbusplus::asio::getProperty<std::string>(
1183 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1184 "/xyz/openbmc_project/control/host0/power_restore_policy",
1185 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1186 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001187 if (ec)
1188 {
1189 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1190 return;
1191 }
1192
George Liu0fda0f12021-11-16 10:06:17 +08001193 const boost::container::flat_map<std::string, std::string> policyMaps = {
1194 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1195 "AlwaysOn"},
1196 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1197 "AlwaysOff"},
1198 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
Matthew Barth4ed47cb2022-03-03 15:58:06 -06001199 "LastState"},
1200 // Return `AlwaysOff` when power restore policy set to "None"
1201 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1202 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001203
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001204 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001205 if (policyMapsIt == policyMaps.end())
1206 {
1207 messages::internalError(aResp->res);
1208 return;
1209 }
1210
1211 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001212 });
George Liuc6a620f2020-04-10 17:18:11 +08001213}
1214
1215/**
Ali Ahmed19817712021-06-29 17:01:52 -05001216 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1217 * TPM is required for booting the host.
1218 *
1219 * @param[in] aResp Shared pointer for generating response message.
1220 *
1221 * @return None.
1222 */
1223inline void getTrustedModuleRequiredToBoot(
1224 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1225{
1226 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1227
1228 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001229 [aResp](const boost::system::error_code ec,
1230 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ali Ahmed19817712021-06-29 17:01:52 -05001231 if (ec)
1232 {
1233 BMCWEB_LOG_DEBUG
1234 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1235 // This is an optional D-Bus object so just return if
1236 // error occurs
1237 return;
1238 }
Ed Tanous26f69762022-01-25 09:49:11 -08001239 if (subtree.empty())
Ali Ahmed19817712021-06-29 17:01:52 -05001240 {
1241 // As noted above, this is an optional interface so just return
1242 // if there is no instance found
1243 return;
1244 }
1245
1246 /* When there is more than one TPMEnable object... */
1247 if (subtree.size() > 1)
1248 {
1249 BMCWEB_LOG_DEBUG
1250 << "DBUS response has more than 1 TPM Enable object:"
1251 << subtree.size();
1252 // Throw an internal Error and return
1253 messages::internalError(aResp->res);
1254 return;
1255 }
1256
1257 // Make sure the Dbus response map has a service and objectPath
1258 // field
1259 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1260 {
1261 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1262 messages::internalError(aResp->res);
1263 return;
1264 }
1265
1266 const std::string& path = subtree[0].first;
1267 const std::string& serv = subtree[0].second.begin()->first;
1268
1269 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001270 sdbusplus::asio::getProperty<bool>(
1271 *crow::connections::systemBus, serv, path,
1272 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1273 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001274 if (ec)
1275 {
1276 BMCWEB_LOG_DEBUG
1277 << "D-BUS response error on TPM.Policy Get" << ec;
1278 messages::internalError(aResp->res);
1279 return;
1280 }
1281
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001282 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001283 {
1284 aResp->res
1285 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1286 "Required";
1287 }
1288 else
1289 {
1290 aResp->res
1291 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1292 "Disabled";
1293 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001294 });
Ali Ahmed19817712021-06-29 17:01:52 -05001295 },
1296 "xyz.openbmc_project.ObjectMapper",
1297 "/xyz/openbmc_project/object_mapper",
1298 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1299 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1300}
1301
1302/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001303 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1304 * TPM is required for booting the host.
1305 *
1306 * @param[in] aResp Shared pointer for generating response message.
1307 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1308 *
1309 * @return None.
1310 */
1311inline void setTrustedModuleRequiredToBoot(
1312 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1313{
1314 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1315
1316 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001317 [aResp, tpmRequired](const boost::system::error_code ec,
1318 dbus::utility::MapperGetSubTreeResponse& subtree) {
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001319 if (ec)
1320 {
1321 BMCWEB_LOG_DEBUG
1322 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1323 messages::internalError(aResp->res);
1324 return;
1325 }
Ed Tanous26f69762022-01-25 09:49:11 -08001326 if (subtree.empty())
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001327 {
1328 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1329 "TrustedModuleRequiredToBoot");
1330 return;
1331 }
1332
1333 /* When there is more than one TPMEnable object... */
1334 if (subtree.size() > 1)
1335 {
1336 BMCWEB_LOG_DEBUG
1337 << "DBUS response has more than 1 TPM Enable object:"
1338 << subtree.size();
1339 // Throw an internal Error and return
1340 messages::internalError(aResp->res);
1341 return;
1342 }
1343
1344 // Make sure the Dbus response map has a service and objectPath
1345 // field
1346 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1347 {
1348 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1349 messages::internalError(aResp->res);
1350 return;
1351 }
1352
1353 const std::string& path = subtree[0].first;
1354 const std::string& serv = subtree[0].second.begin()->first;
1355
1356 if (serv.empty())
1357 {
1358 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1359 messages::internalError(aResp->res);
1360 return;
1361 }
1362
1363 // Valid TPM Enable object found, now setting the value
1364 crow::connections::systemBus->async_method_call(
1365 [aResp](const boost::system::error_code ec) {
1366 if (ec)
1367 {
George Liu0fda0f12021-11-16 10:06:17 +08001368 BMCWEB_LOG_DEBUG
1369 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1370 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001371 messages::internalError(aResp->res);
1372 return;
1373 }
1374 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1375 },
1376 serv, path, "org.freedesktop.DBus.Properties", "Set",
1377 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001378 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001379 },
1380 "xyz.openbmc_project.ObjectMapper",
1381 "/xyz/openbmc_project/object_mapper",
1382 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1383 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1384}
1385
1386/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301387 * @brief Sets boot properties into DBUS object(s).
1388 *
1389 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001390 * @param[in] bootType The boot type to set.
1391 * @return Integer error code.
1392 */
1393inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001394 const std::optional<std::string>& bootType)
1395{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001396 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001397
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001398 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001399 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001400 return;
1401 }
1402
1403 // Source target specified
1404 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1405 // Figure out which DBUS interface and property to use
1406 if (*bootType == "Legacy")
1407 {
1408 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1409 }
1410 else if (*bootType == "UEFI")
1411 {
1412 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1413 }
1414 else
1415 {
1416 BMCWEB_LOG_DEBUG << "Invalid property value for "
1417 "BootSourceOverrideMode: "
1418 << *bootType;
1419 messages::propertyValueNotInList(aResp->res, *bootType,
1420 "BootSourceOverrideMode");
1421 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001422 }
1423
1424 // Act on validated parameters
1425 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1426
1427 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001428 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001429 if (ec)
1430 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001431 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1432 if (ec.value() == boost::asio::error::host_unreachable)
1433 {
1434 messages::resourceNotFound(aResp->res, "Set", "BootType");
1435 return;
1436 }
1437 messages::internalError(aResp->res);
1438 return;
1439 }
1440 BMCWEB_LOG_DEBUG << "Boot type update done.";
1441 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001442 "xyz.openbmc_project.Settings",
1443 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001444 "org.freedesktop.DBus.Properties", "Set",
1445 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001446 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001447}
1448
1449/**
1450 * @brief Sets boot properties into DBUS object(s).
1451 *
1452 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001453 * @param[in] bootType The boot type to set.
1454 * @return Integer error code.
1455 */
1456inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1457 const std::optional<std::string>& bootEnable)
1458{
1459 if (!bootEnable)
1460 {
1461 return;
1462 }
1463 // Source target specified
1464 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1465
1466 bool bootOverrideEnable = false;
1467 bool bootOverridePersistent = false;
1468 // Figure out which DBUS interface and property to use
1469 if (*bootEnable == "Disabled")
1470 {
1471 bootOverrideEnable = false;
1472 }
1473 else if (*bootEnable == "Once")
1474 {
1475 bootOverrideEnable = true;
1476 bootOverridePersistent = false;
1477 }
1478 else if (*bootEnable == "Continuous")
1479 {
1480 bootOverrideEnable = true;
1481 bootOverridePersistent = true;
1482 }
1483 else
1484 {
George Liu0fda0f12021-11-16 10:06:17 +08001485 BMCWEB_LOG_DEBUG
1486 << "Invalid property value for BootSourceOverrideEnabled: "
1487 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001488 messages::propertyValueNotInList(aResp->res, *bootEnable,
1489 "BootSourceOverrideEnabled");
1490 return;
1491 }
1492
1493 // Act on validated parameters
1494 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1495
1496 crow::connections::systemBus->async_method_call(
1497 [aResp](const boost::system::error_code ec) {
1498 if (ec)
1499 {
1500 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1501 messages::internalError(aResp->res);
1502 return;
1503 }
1504 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1505 },
1506 "xyz.openbmc_project.Settings",
1507 "/xyz/openbmc_project/control/host0/boot",
1508 "org.freedesktop.DBus.Properties", "Set",
1509 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001510 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001511
1512 if (!bootOverrideEnable)
1513 {
1514 return;
1515 }
1516
1517 // In case boot override is enabled we need to set correct value for the
1518 // 'one_time' enable DBus interface
1519 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1520 << bootOverridePersistent;
1521
1522 crow::connections::systemBus->async_method_call(
1523 [aResp](const boost::system::error_code ec) {
1524 if (ec)
1525 {
1526 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1527 messages::internalError(aResp->res);
1528 return;
1529 }
1530 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1531 },
1532 "xyz.openbmc_project.Settings",
1533 "/xyz/openbmc_project/control/host0/boot/one_time",
1534 "org.freedesktop.DBus.Properties", "Set",
1535 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001536 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001537}
1538
1539/**
1540 * @brief Sets boot properties into DBUS object(s).
1541 *
1542 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301543 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301544 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001545 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301546 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001547inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001548 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301549{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001550 std::string bootSourceStr;
1551 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001552
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001553 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301554 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001555 return;
1556 }
1557
1558 // Source target specified
1559 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1560 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001561 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1562 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001563 {
1564 BMCWEB_LOG_DEBUG
1565 << "Invalid property value for BootSourceOverrideTarget: "
1566 << *bootSource;
1567 messages::propertyValueNotInList(aResp->res, *bootSource,
1568 "BootSourceTargetOverride");
1569 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001570 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301571
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001572 // Act on validated parameters
1573 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1574 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001575
1576 crow::connections::systemBus->async_method_call(
1577 [aResp](const boost::system::error_code ec) {
1578 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301579 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001580 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1581 messages::internalError(aResp->res);
1582 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301583 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001584 BMCWEB_LOG_DEBUG << "Boot source update done.";
1585 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001586 "xyz.openbmc_project.Settings",
1587 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001588 "org.freedesktop.DBus.Properties", "Set",
1589 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001590 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001591
1592 crow::connections::systemBus->async_method_call(
1593 [aResp](const boost::system::error_code ec) {
1594 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301595 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001596 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1597 messages::internalError(aResp->res);
1598 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301599 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001600 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1601 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001602 "xyz.openbmc_project.Settings",
1603 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001604 "org.freedesktop.DBus.Properties", "Set",
1605 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001606 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001607}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001608
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001609/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001610 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301611 *
1612 * @param[in] aResp Shared pointer for generating response message.
1613 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001614 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301615 * @param[in] bootEnable The boot override enable from incoming RF request.
1616 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001617 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301618 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001619
1620inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1621 const std::optional<std::string>& bootSource,
1622 const std::optional<std::string>& bootType,
1623 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301624{
1625 BMCWEB_LOG_DEBUG << "Set boot information.";
1626
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001627 setBootModeOrSource(aResp, bootSource);
1628 setBootType(aResp, bootType);
1629 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301630}
1631
George Liuc6a620f2020-04-10 17:18:11 +08001632/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001633 * @brief Sets AssetTag
1634 *
1635 * @param[in] aResp Shared pointer for generating response message.
1636 * @param[in] assetTag "AssetTag" from request.
1637 *
1638 * @return None.
1639 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001640inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001641 const std::string& assetTag)
1642{
1643 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001644 [aResp,
1645 assetTag](const boost::system::error_code ec,
1646 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Gunnar Mills98e386e2020-10-30 14:58:09 -05001647 if (ec)
1648 {
1649 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1650 messages::internalError(aResp->res);
1651 return;
1652 }
Ed Tanous26f69762022-01-25 09:49:11 -08001653 if (subtree.empty())
Gunnar Mills98e386e2020-10-30 14:58:09 -05001654 {
1655 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1656 messages::internalError(aResp->res);
1657 return;
1658 }
1659 // Assume only 1 system D-Bus object
1660 // Throw an error if there is more than 1
1661 if (subtree.size() > 1)
1662 {
1663 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1664 messages::internalError(aResp->res);
1665 return;
1666 }
1667 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1668 {
1669 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1670 messages::internalError(aResp->res);
1671 return;
1672 }
1673
1674 const std::string& path = subtree[0].first;
1675 const std::string& service = subtree[0].second.begin()->first;
1676
1677 if (service.empty())
1678 {
1679 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1680 messages::internalError(aResp->res);
1681 return;
1682 }
1683
1684 crow::connections::systemBus->async_method_call(
1685 [aResp](const boost::system::error_code ec2) {
1686 if (ec2)
1687 {
1688 BMCWEB_LOG_DEBUG
1689 << "D-Bus response error on AssetTag Set " << ec2;
1690 messages::internalError(aResp->res);
1691 return;
1692 }
1693 },
1694 service, path, "org.freedesktop.DBus.Properties", "Set",
1695 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001696 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001697 },
1698 "xyz.openbmc_project.ObjectMapper",
1699 "/xyz/openbmc_project/object_mapper",
1700 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1701 "/xyz/openbmc_project/inventory", int32_t(0),
1702 std::array<const char*, 1>{
1703 "xyz.openbmc_project.Inventory.Item.System"});
1704}
1705
1706/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001707 * @brief Sets automaticRetry (Auto Reboot)
1708 *
1709 * @param[in] aResp Shared pointer for generating response message.
1710 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1711 *
1712 * @return None.
1713 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001714inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001715 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001716{
1717 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1718
1719 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001720 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001721
1722 if (automaticRetryConfig == "Disabled")
1723 {
1724 autoRebootEnabled = false;
1725 }
1726 else if (automaticRetryConfig == "RetryAttempts")
1727 {
1728 autoRebootEnabled = true;
1729 }
1730 else
1731 {
George Liu0fda0f12021-11-16 10:06:17 +08001732 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001733 << automaticRetryConfig;
1734 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1735 "AutomaticRetryConfig");
1736 return;
1737 }
1738
1739 crow::connections::systemBus->async_method_call(
1740 [aResp](const boost::system::error_code ec) {
1741 if (ec)
1742 {
1743 messages::internalError(aResp->res);
1744 return;
1745 }
1746 },
1747 "xyz.openbmc_project.Settings",
1748 "/xyz/openbmc_project/control/host0/auto_reboot",
1749 "org.freedesktop.DBus.Properties", "Set",
1750 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001751 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001752}
1753
1754/**
George Liuc6a620f2020-04-10 17:18:11 +08001755 * @brief Sets power restore policy properties.
1756 *
1757 * @param[in] aResp Shared pointer for generating response message.
1758 * @param[in] policy power restore policy properties from request.
1759 *
1760 * @return None.
1761 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001762inline void
1763 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1764 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001765{
1766 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1767
1768 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001769 {"AlwaysOn",
1770 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1771 {"AlwaysOff",
1772 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1773 {"LastState",
1774 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001775
1776 std::string powerRestorPolicy;
1777
Gunnar Mills4e69c902021-01-05 19:50:11 -06001778 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001779 if (policyMapsIt == policyMaps.end())
1780 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001781 messages::propertyValueNotInList(aResp->res, policy,
1782 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001783 return;
1784 }
1785
1786 powerRestorPolicy = policyMapsIt->second;
1787
1788 crow::connections::systemBus->async_method_call(
1789 [aResp](const boost::system::error_code ec) {
1790 if (ec)
1791 {
1792 messages::internalError(aResp->res);
1793 return;
1794 }
1795 },
1796 "xyz.openbmc_project.Settings",
1797 "/xyz/openbmc_project/control/host0/power_restore_policy",
1798 "org.freedesktop.DBus.Properties", "Set",
1799 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001800 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001801}
1802
AppaRao Pulia6349912019-10-18 17:16:08 +05301803#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1804/**
1805 * @brief Retrieves provisioning status
1806 *
1807 * @param[in] aResp Shared pointer for completing asynchronous calls.
1808 *
1809 * @return None.
1810 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001811inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301812{
1813 BMCWEB_LOG_DEBUG << "Get OEM information.";
1814 crow::connections::systemBus->async_method_call(
1815 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001816 const dbus::utility::DBusPropertiesMap& propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301817 nlohmann::json& oemPFR =
1818 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001819 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1820 "#OemComputerSystem.OpenBmc";
1821 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1822
AppaRao Pulia6349912019-10-18 17:16:08 +05301823 if (ec)
1824 {
1825 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301826 // not an error, don't have to have the interface
1827 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301828 return;
1829 }
1830
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001831 const bool* provState = nullptr;
1832 const bool* lockState = nullptr;
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001833 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1834 property : propertiesList)
AppaRao Pulia6349912019-10-18 17:16:08 +05301835 {
1836 if (property.first == "UfmProvisioned")
1837 {
1838 provState = std::get_if<bool>(&property.second);
1839 }
1840 else if (property.first == "UfmLocked")
1841 {
1842 lockState = std::get_if<bool>(&property.second);
1843 }
1844 }
1845
1846 if ((provState == nullptr) || (lockState == nullptr))
1847 {
1848 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1849 messages::internalError(aResp->res);
1850 return;
1851 }
1852
AppaRao Pulia6349912019-10-18 17:16:08 +05301853 if (*provState == true)
1854 {
1855 if (*lockState == true)
1856 {
1857 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1858 }
1859 else
1860 {
1861 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1862 }
1863 }
1864 else
1865 {
1866 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1867 }
1868 },
1869 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1870 "org.freedesktop.DBus.Properties", "GetAll",
1871 "xyz.openbmc_project.PFR.Attributes");
1872}
1873#endif
1874
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301875/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001876 * @brief Translate the PowerMode to a response message.
1877 *
1878 * @param[in] aResp Shared pointer for generating response message.
1879 * @param[in] modeValue PowerMode value to be translated
1880 *
1881 * @return None.
1882 */
1883inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1884 const std::string& modeValue)
1885{
1886 std::string modeString;
1887
George Liu0fda0f12021-11-16 10:06:17 +08001888 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001889 {
1890 aResp->res.jsonValue["PowerMode"] = "Static";
1891 }
George Liu0fda0f12021-11-16 10:06:17 +08001892 else if (
1893 modeValue ==
1894 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001895 {
1896 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1897 }
George Liu0fda0f12021-11-16 10:06:17 +08001898 else if (modeValue ==
1899 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001900 {
1901 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1902 }
George Liu0fda0f12021-11-16 10:06:17 +08001903 else if (modeValue ==
1904 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001905 {
1906 aResp->res.jsonValue["PowerMode"] = "OEM";
1907 }
1908 else
1909 {
1910 // Any other values would be invalid
1911 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1912 messages::internalError(aResp->res);
1913 }
1914}
1915
1916/**
1917 * @brief Retrieves system power mode
1918 *
1919 * @param[in] aResp Shared pointer for generating response message.
1920 *
1921 * @return None.
1922 */
1923inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1924{
1925 BMCWEB_LOG_DEBUG << "Get power mode.";
1926
1927 // Get Power Mode object path:
1928 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001929 [aResp](const boost::system::error_code ec,
1930 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001931 if (ec)
1932 {
1933 BMCWEB_LOG_DEBUG
1934 << "DBUS response error on Power.Mode GetSubTree " << ec;
1935 // This is an optional D-Bus object so just return if
1936 // error occurs
1937 return;
1938 }
1939 if (subtree.empty())
1940 {
1941 // As noted above, this is an optional interface so just return
1942 // if there is no instance found
1943 return;
1944 }
1945 if (subtree.size() > 1)
1946 {
1947 // More then one PowerMode object is not supported and is an
1948 // error
1949 BMCWEB_LOG_DEBUG
1950 << "Found more than 1 system D-Bus Power.Mode objects: "
1951 << subtree.size();
1952 messages::internalError(aResp->res);
1953 return;
1954 }
1955 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1956 {
1957 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1958 messages::internalError(aResp->res);
1959 return;
1960 }
1961 const std::string& path = subtree[0].first;
1962 const std::string& service = subtree[0].second.begin()->first;
1963 if (service.empty())
1964 {
1965 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1966 messages::internalError(aResp->res);
1967 return;
1968 }
1969 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001970 sdbusplus::asio::getProperty<std::string>(
1971 *crow::connections::systemBus, service, path,
1972 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001973 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001974 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001975 if (ec)
1976 {
1977 BMCWEB_LOG_DEBUG
1978 << "DBUS response error on PowerMode Get: " << ec;
1979 messages::internalError(aResp->res);
1980 return;
1981 }
1982
Chris Cain3a2d04242021-05-28 16:57:10 -05001983 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1984 {"Static", "MaximumPerformance", "PowerSaving"};
1985
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001986 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1987 translatePowerMode(aResp, pmode);
1988 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001989 },
1990 "xyz.openbmc_project.ObjectMapper",
1991 "/xyz/openbmc_project/object_mapper",
1992 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1993 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1994}
1995
1996/**
1997 * @brief Validate the specified mode is valid and return the PowerMode
1998 * name associated with that string
1999 *
2000 * @param[in] aResp Shared pointer for generating response message.
2001 * @param[in] modeString String representing the desired PowerMode
2002 *
2003 * @return PowerMode value or empty string if mode is not valid
2004 */
2005inline std::string
2006 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2007 const std::string& modeString)
2008{
2009 std::string mode;
2010
2011 if (modeString == "Static")
2012 {
2013 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2014 }
2015 else if (modeString == "MaximumPerformance")
2016 {
George Liu0fda0f12021-11-16 10:06:17 +08002017 mode =
2018 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002019 }
2020 else if (modeString == "PowerSaving")
2021 {
2022 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2023 }
2024 else
2025 {
2026 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2027 }
2028 return mode;
2029}
2030
2031/**
2032 * @brief Sets system power mode.
2033 *
2034 * @param[in] aResp Shared pointer for generating response message.
2035 * @param[in] pmode System power mode from request.
2036 *
2037 * @return None.
2038 */
2039inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2040 const std::string& pmode)
2041{
2042 BMCWEB_LOG_DEBUG << "Set power mode.";
2043
2044 std::string powerMode = validatePowerMode(aResp, pmode);
2045 if (powerMode.empty())
2046 {
2047 return;
2048 }
2049
2050 // Get Power Mode object path:
2051 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002052 [aResp,
2053 powerMode](const boost::system::error_code ec,
2054 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002055 if (ec)
2056 {
2057 BMCWEB_LOG_DEBUG
2058 << "DBUS response error on Power.Mode GetSubTree " << ec;
2059 // This is an optional D-Bus object, but user attempted to patch
2060 messages::internalError(aResp->res);
2061 return;
2062 }
2063 if (subtree.empty())
2064 {
2065 // This is an optional D-Bus object, but user attempted to patch
2066 messages::resourceNotFound(aResp->res, "ComputerSystem",
2067 "PowerMode");
2068 return;
2069 }
2070 if (subtree.size() > 1)
2071 {
2072 // More then one PowerMode object is not supported and is an
2073 // error
2074 BMCWEB_LOG_DEBUG
2075 << "Found more than 1 system D-Bus Power.Mode objects: "
2076 << subtree.size();
2077 messages::internalError(aResp->res);
2078 return;
2079 }
2080 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2081 {
2082 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2083 messages::internalError(aResp->res);
2084 return;
2085 }
2086 const std::string& path = subtree[0].first;
2087 const std::string& service = subtree[0].second.begin()->first;
2088 if (service.empty())
2089 {
2090 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2091 messages::internalError(aResp->res);
2092 return;
2093 }
2094
2095 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2096 << path;
2097
2098 // Set the Power Mode property
2099 crow::connections::systemBus->async_method_call(
2100 [aResp](const boost::system::error_code ec) {
2101 if (ec)
2102 {
2103 messages::internalError(aResp->res);
2104 return;
2105 }
2106 },
2107 service, path, "org.freedesktop.DBus.Properties", "Set",
2108 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002109 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002110 },
2111 "xyz.openbmc_project.ObjectMapper",
2112 "/xyz/openbmc_project/object_mapper",
2113 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2114 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2115}
2116
2117/**
Yong Li51709ff2019-09-30 14:13:04 +08002118 * @brief Translates watchdog timeout action DBUS property value to redfish.
2119 *
2120 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2121 *
2122 * @return Returns as a string, the timeout action in Redfish terms. If
2123 * translation cannot be done, returns an empty string.
2124 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002125inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002126{
2127 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2128 {
2129 return "None";
2130 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002131 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002132 {
2133 return "ResetSystem";
2134 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002135 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002136 {
2137 return "PowerDown";
2138 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002139 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002140 {
2141 return "PowerCycle";
2142 }
2143
2144 return "";
2145}
2146
2147/**
Yong Lic45f0082019-10-10 14:19:01 +08002148 *@brief Translates timeout action from Redfish to DBUS property value.
2149 *
2150 *@param[in] rfAction The timeout action in Redfish.
2151 *
2152 *@return Returns as a string, the time_out action as expected by DBUS.
2153 *If translation cannot be done, returns an empty string.
2154 */
2155
Ed Tanous23a21a12020-07-25 04:45:05 +00002156inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002157{
2158 if (rfAction == "None")
2159 {
2160 return "xyz.openbmc_project.State.Watchdog.Action.None";
2161 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002162 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002163 {
2164 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002167 {
2168 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002170 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002171 {
2172 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2173 }
2174
2175 return "";
2176}
2177
2178/**
Yong Li51709ff2019-09-30 14:13:04 +08002179 * @brief Retrieves host watchdog timer properties over DBUS
2180 *
2181 * @param[in] aResp Shared pointer for completing asynchronous calls.
2182 *
2183 * @return None.
2184 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002185inline void
2186 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002187{
2188 BMCWEB_LOG_DEBUG << "Get host watchodg";
2189 crow::connections::systemBus->async_method_call(
2190 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002191 const dbus::utility::DBusPropertiesMap& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002192 if (ec)
2193 {
2194 // watchdog service is stopped
2195 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2196 return;
2197 }
2198
2199 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2200
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002201 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002202 aResp->res.jsonValue["HostWatchdogTimer"];
2203
2204 // watchdog service is running/enabled
2205 hostWatchdogTimer["Status"]["State"] = "Enabled";
2206
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002207 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002208 {
2209 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2210 if (property.first == "Enabled")
2211 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002212 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002213
Ed Tanouse662eae2022-01-25 10:39:19 -08002214 if (state == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002215 {
2216 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002217 return;
Yong Li51709ff2019-09-30 14:13:04 +08002218 }
2219
2220 hostWatchdogTimer["FunctionEnabled"] = *state;
2221 }
2222 else if (property.first == "ExpireAction")
2223 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002224 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002225 std::get_if<std::string>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002226 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002227 {
2228 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002229 return;
Yong Li51709ff2019-09-30 14:13:04 +08002230 }
2231
2232 std::string action = dbusToRfWatchdogAction(*s);
2233 if (action.empty())
2234 {
2235 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002236 return;
Yong Li51709ff2019-09-30 14:13:04 +08002237 }
2238 hostWatchdogTimer["TimeoutAction"] = action;
2239 }
2240 }
2241 },
2242 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2243 "org.freedesktop.DBus.Properties", "GetAll",
2244 "xyz.openbmc_project.State.Watchdog");
2245}
2246
2247/**
Yong Lic45f0082019-10-10 14:19:01 +08002248 * @brief Sets Host WatchDog Timer properties.
2249 *
2250 * @param[in] aResp Shared pointer for generating response message.
2251 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2252 * RF request.
2253 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2254 *
2255 * @return None.
2256 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002257inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002258 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002259 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002260{
2261 BMCWEB_LOG_DEBUG << "Set host watchdog";
2262
2263 if (wdtTimeOutAction)
2264 {
2265 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2266 // check if TimeOut Action is Valid
2267 if (wdtTimeOutActStr.empty())
2268 {
2269 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2270 << *wdtTimeOutAction;
2271 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2272 "TimeoutAction");
2273 return;
2274 }
2275
2276 crow::connections::systemBus->async_method_call(
2277 [aResp](const boost::system::error_code ec) {
2278 if (ec)
2279 {
2280 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2281 messages::internalError(aResp->res);
2282 return;
2283 }
2284 },
2285 "xyz.openbmc_project.Watchdog",
2286 "/xyz/openbmc_project/watchdog/host0",
2287 "org.freedesktop.DBus.Properties", "Set",
2288 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002289 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002290 }
2291
2292 if (wdtEnable)
2293 {
2294 crow::connections::systemBus->async_method_call(
2295 [aResp](const boost::system::error_code ec) {
2296 if (ec)
2297 {
2298 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2299 messages::internalError(aResp->res);
2300 return;
2301 }
2302 },
2303 "xyz.openbmc_project.Watchdog",
2304 "/xyz/openbmc_project/watchdog/host0",
2305 "org.freedesktop.DBus.Properties", "Set",
2306 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002307 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002308 }
2309}
2310
Chris Cain37bbf982021-09-20 10:53:09 -05002311using ipsPropertiesType =
2312 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2313/**
2314 * @brief Parse the Idle Power Saver properties into json
2315 *
2316 * @param[in] aResp Shared pointer for completing asynchronous calls.
2317 * @param[in] properties IPS property data from DBus.
2318 *
2319 * @return true if successful
2320 */
Ed Tanousf6674222021-11-13 09:41:41 -08002321inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2322 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002323{
2324 for (const auto& property : properties)
2325 {
2326 if (property.first == "Enabled")
2327 {
2328 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002329 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002330 {
2331 return false;
2332 }
2333 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2334 }
2335 else if (property.first == "EnterUtilizationPercent")
2336 {
2337 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002338 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002339 {
2340 return false;
2341 }
2342 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2343 }
2344 else if (property.first == "EnterDwellTime")
2345 {
2346 // Convert Dbus time from milliseconds to seconds
2347 const uint64_t* timeMilliseconds =
2348 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002349 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002350 {
2351 return false;
2352 }
2353 const std::chrono::duration<uint64_t, std::milli> ms(
2354 *timeMilliseconds);
2355 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2356 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2357 .count();
2358 }
2359 else if (property.first == "ExitUtilizationPercent")
2360 {
2361 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002362 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002363 {
2364 return false;
2365 }
2366 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2367 }
2368 else if (property.first == "ExitDwellTime")
2369 {
2370 // Convert Dbus time from milliseconds to seconds
2371 const uint64_t* timeMilliseconds =
2372 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002373 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002374 {
2375 return false;
2376 }
2377 const std::chrono::duration<uint64_t, std::milli> ms(
2378 *timeMilliseconds);
2379 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2380 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2381 .count();
2382 }
2383 else
2384 {
2385 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2386 << property.first;
2387 }
2388 }
2389
2390 return true;
2391}
2392
2393/**
2394 * @brief Retrieves host watchdog timer properties over DBUS
2395 *
2396 * @param[in] aResp Shared pointer for completing asynchronous calls.
2397 *
2398 * @return None.
2399 */
2400inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2401{
2402 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2403
2404 // Get IdlePowerSaver object path:
2405 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002406 [aResp](const boost::system::error_code ec,
2407 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain37bbf982021-09-20 10:53:09 -05002408 if (ec)
2409 {
2410 BMCWEB_LOG_DEBUG
2411 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2412 << ec;
2413 messages::internalError(aResp->res);
2414 return;
2415 }
2416 if (subtree.empty())
2417 {
2418 // This is an optional interface so just return
2419 // if there is no instance found
2420 BMCWEB_LOG_DEBUG << "No instances found";
2421 return;
2422 }
2423 if (subtree.size() > 1)
2424 {
2425 // More then one PowerIdlePowerSaver object is not supported and
2426 // is an error
2427 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2428 "Power.IdlePowerSaver objects: "
2429 << subtree.size();
2430 messages::internalError(aResp->res);
2431 return;
2432 }
2433 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2434 {
2435 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2436 messages::internalError(aResp->res);
2437 return;
2438 }
2439 const std::string& path = subtree[0].first;
2440 const std::string& service = subtree[0].second.begin()->first;
2441 if (service.empty())
2442 {
2443 BMCWEB_LOG_DEBUG
2444 << "Power.IdlePowerSaver service mapper error!";
2445 messages::internalError(aResp->res);
2446 return;
2447 }
2448
2449 // Valid IdlePowerSaver object found, now read the current values
2450 crow::connections::systemBus->async_method_call(
2451 [aResp](const boost::system::error_code ec,
2452 ipsPropertiesType& properties) {
2453 if (ec)
2454 {
2455 BMCWEB_LOG_ERROR
2456 << "DBUS response error on IdlePowerSaver GetAll: "
2457 << ec;
2458 messages::internalError(aResp->res);
2459 return;
2460 }
2461
Ed Tanouse05aec52022-01-25 10:28:56 -08002462 if (!parseIpsProperties(aResp, properties))
Chris Cain37bbf982021-09-20 10:53:09 -05002463 {
2464 messages::internalError(aResp->res);
2465 return;
2466 }
2467 },
2468 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2469 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2470 },
2471 "xyz.openbmc_project.ObjectMapper",
2472 "/xyz/openbmc_project/object_mapper",
2473 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2474 std::array<const char*, 1>{
2475 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2476
2477 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2478}
2479
2480/**
2481 * @brief Sets Idle Power Saver properties.
2482 *
2483 * @param[in] aResp Shared pointer for generating response message.
2484 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2485 * RF request.
2486 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2487 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2488 * before entering idle state.
2489 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2490 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2491 * before exiting idle state
2492 *
2493 * @return None.
2494 */
2495inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2496 const std::optional<bool> ipsEnable,
2497 const std::optional<uint8_t> ipsEnterUtil,
2498 const std::optional<uint64_t> ipsEnterTime,
2499 const std::optional<uint8_t> ipsExitUtil,
2500 const std::optional<uint64_t> ipsExitTime)
2501{
2502 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2503
2504 // Get IdlePowerSaver object path:
2505 crow::connections::systemBus->async_method_call(
2506 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002507 ipsExitTime](const boost::system::error_code ec,
2508 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Chris Cain37bbf982021-09-20 10:53:09 -05002509 if (ec)
2510 {
2511 BMCWEB_LOG_DEBUG
2512 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2513 << ec;
2514 messages::internalError(aResp->res);
2515 return;
2516 }
2517 if (subtree.empty())
2518 {
2519 // This is an optional D-Bus object, but user attempted to patch
2520 messages::resourceNotFound(aResp->res, "ComputerSystem",
2521 "IdlePowerSaver");
2522 return;
2523 }
2524 if (subtree.size() > 1)
2525 {
2526 // More then one PowerIdlePowerSaver object is not supported and
2527 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002528 BMCWEB_LOG_DEBUG
2529 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2530 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002531 messages::internalError(aResp->res);
2532 return;
2533 }
2534 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2535 {
2536 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2537 messages::internalError(aResp->res);
2538 return;
2539 }
2540 const std::string& path = subtree[0].first;
2541 const std::string& service = subtree[0].second.begin()->first;
2542 if (service.empty())
2543 {
2544 BMCWEB_LOG_DEBUG
2545 << "Power.IdlePowerSaver service mapper error!";
2546 messages::internalError(aResp->res);
2547 return;
2548 }
2549
2550 // Valid Power IdlePowerSaver object found, now set any values that
2551 // need to be updated
2552
2553 if (ipsEnable)
2554 {
2555 crow::connections::systemBus->async_method_call(
2556 [aResp](const boost::system::error_code ec) {
2557 if (ec)
2558 {
2559 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2560 messages::internalError(aResp->res);
2561 return;
2562 }
2563 },
2564 service, path, "org.freedesktop.DBus.Properties", "Set",
2565 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002566 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002567 }
2568 if (ipsEnterUtil)
2569 {
2570 crow::connections::systemBus->async_method_call(
2571 [aResp](const boost::system::error_code ec) {
2572 if (ec)
2573 {
2574 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2575 messages::internalError(aResp->res);
2576 return;
2577 }
2578 },
2579 service, path, "org.freedesktop.DBus.Properties", "Set",
2580 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2581 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002582 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002583 }
2584 if (ipsEnterTime)
2585 {
2586 // Convert from seconds into milliseconds for DBus
2587 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2588 crow::connections::systemBus->async_method_call(
2589 [aResp](const boost::system::error_code ec) {
2590 if (ec)
2591 {
2592 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2593 messages::internalError(aResp->res);
2594 return;
2595 }
2596 },
2597 service, path, "org.freedesktop.DBus.Properties", "Set",
2598 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002599 "EnterDwellTime",
2600 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002601 }
2602 if (ipsExitUtil)
2603 {
2604 crow::connections::systemBus->async_method_call(
2605 [aResp](const boost::system::error_code ec) {
2606 if (ec)
2607 {
2608 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2609 messages::internalError(aResp->res);
2610 return;
2611 }
2612 },
2613 service, path, "org.freedesktop.DBus.Properties", "Set",
2614 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2615 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002616 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002617 }
2618 if (ipsExitTime)
2619 {
2620 // Convert from seconds into milliseconds for DBus
2621 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2622 crow::connections::systemBus->async_method_call(
2623 [aResp](const boost::system::error_code ec) {
2624 if (ec)
2625 {
2626 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2627 messages::internalError(aResp->res);
2628 return;
2629 }
2630 },
2631 service, path, "org.freedesktop.DBus.Properties", "Set",
2632 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002633 "ExitDwellTime",
2634 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002635 }
2636 },
2637 "xyz.openbmc_project.ObjectMapper",
2638 "/xyz/openbmc_project/object_mapper",
2639 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2640 std::array<const char*, 1>{
2641 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2642
2643 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2644}
2645
Yong Lic45f0082019-10-10 14:19:01 +08002646/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002647 * SystemsCollection derived class for delivering ComputerSystems Collection
2648 * Schema
2649 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002650inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002651{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002652 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002653 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002654 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002655 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002656 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2657 asyncResp->res.jsonValue["@odata.type"] =
2658 "#ComputerSystemCollection.ComputerSystemCollection";
2659 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2660 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002661
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002662 sdbusplus::asio::getProperty<std::string>(
2663 *crow::connections::systemBus,
2664 "xyz.openbmc_project.Settings",
2665 "/xyz/openbmc_project/network/hypervisor",
2666 "xyz.openbmc_project.Network.SystemConfiguration",
2667 "HostName",
2668 [asyncResp](const boost::system::error_code ec,
2669 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002670 nlohmann::json& ifaceArray =
2671 asyncResp->res.jsonValue["Members"];
2672 ifaceArray = nlohmann::json::array();
2673 auto& count =
2674 asyncResp->res.jsonValue["Members@odata.count"];
2675 ifaceArray.push_back(
2676 {{"@odata.id", "/redfish/v1/Systems/system"}});
2677 count = ifaceArray.size();
2678 if (!ec)
2679 {
2680 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2681 ifaceArray.push_back(
2682 {{"@odata.id",
2683 "/redfish/v1/Systems/hypervisor"}});
2684 count = ifaceArray.size();
2685 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002686 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002687 });
2688}
Sunitha Harish462023a2020-02-19 08:34:59 -06002689
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002690/**
2691 * Function transceives data with dbus directly.
2692 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002693inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002694{
2695 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2696 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2697 constexpr char const* interfaceName =
2698 "xyz.openbmc_project.Control.Host.NMI";
2699 constexpr char const* method = "NMI";
2700
2701 crow::connections::systemBus->async_method_call(
2702 [asyncResp](const boost::system::error_code ec) {
2703 if (ec)
2704 {
2705 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2706 messages::internalError(asyncResp->res);
2707 return;
2708 }
2709 messages::success(asyncResp->res);
2710 },
2711 serviceName, objectPath, interfaceName, method);
2712}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002713
2714/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002715 * SystemActionsReset class supports handle POST method for Reset action.
2716 * The class retrieves and sends data directly to D-Bus.
2717 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002718inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002719{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002720 /**
2721 * Function handles POST method request.
2722 * Analyzes POST body message before sends Reset request data to D-Bus.
2723 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002724 BMCWEB_ROUTE(app,
2725 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002726 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002727 .methods(
2728 boost::beast::http::verb::
2729 post)([](const crow::Request& req,
2730 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2731 std::string resetType;
Willy Tu15ed6782021-12-14 11:03:16 -08002732 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2733 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002734 {
2735 return;
2736 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002737
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002738 // Get the command and host vs. chassis
2739 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002740 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002741 if ((resetType == "On") || (resetType == "ForceOn"))
2742 {
2743 command = "xyz.openbmc_project.State.Host.Transition.On";
2744 hostCommand = true;
2745 }
2746 else if (resetType == "ForceOff")
2747 {
2748 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2749 hostCommand = false;
2750 }
2751 else if (resetType == "ForceRestart")
2752 {
2753 command =
2754 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2755 hostCommand = true;
2756 }
2757 else if (resetType == "GracefulShutdown")
2758 {
2759 command = "xyz.openbmc_project.State.Host.Transition.Off";
2760 hostCommand = true;
2761 }
2762 else if (resetType == "GracefulRestart")
2763 {
George Liu0fda0f12021-11-16 10:06:17 +08002764 command =
2765 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002766 hostCommand = true;
2767 }
2768 else if (resetType == "PowerCycle")
2769 {
2770 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2771 hostCommand = true;
2772 }
2773 else if (resetType == "Nmi")
2774 {
2775 doNMI(asyncResp);
2776 return;
2777 }
2778 else
2779 {
2780 messages::actionParameterUnknown(asyncResp->res, "Reset",
2781 resetType);
2782 return;
2783 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002784
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002785 if (hostCommand)
2786 {
2787 crow::connections::systemBus->async_method_call(
2788 [asyncResp, resetType](const boost::system::error_code ec) {
2789 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002790 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002791 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2792 if (ec.value() ==
2793 boost::asio::error::invalid_argument)
2794 {
2795 messages::actionParameterNotSupported(
2796 asyncResp->res, resetType, "Reset");
2797 }
2798 else
2799 {
2800 messages::internalError(asyncResp->res);
2801 }
2802 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002803 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002804 messages::success(asyncResp->res);
2805 },
2806 "xyz.openbmc_project.State.Host",
2807 "/xyz/openbmc_project/state/host0",
2808 "org.freedesktop.DBus.Properties", "Set",
2809 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002810 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002811 }
2812 else
2813 {
2814 crow::connections::systemBus->async_method_call(
2815 [asyncResp, resetType](const boost::system::error_code ec) {
2816 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002817 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002818 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2819 if (ec.value() ==
2820 boost::asio::error::invalid_argument)
2821 {
2822 messages::actionParameterNotSupported(
2823 asyncResp->res, resetType, "Reset");
2824 }
2825 else
2826 {
2827 messages::internalError(asyncResp->res);
2828 }
2829 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002830 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 messages::success(asyncResp->res);
2832 },
2833 "xyz.openbmc_project.State.Chassis",
2834 "/xyz/openbmc_project/state/chassis0",
2835 "org.freedesktop.DBus.Properties", "Set",
2836 "xyz.openbmc_project.State.Chassis",
2837 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002838 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839 }
2840 });
2841}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002842
2843/**
Ed Tanous66173382018-08-15 18:20:59 -07002844 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002845 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002846inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002847{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002848
Ed Tanous1abe55e2018-09-05 08:30:59 -07002849 /**
2850 * Functions triggers appropriate requests on DBus
2851 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002852 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002853 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002854 .methods(
2855 boost::beast::http::verb::
2856 get)([](const crow::Request&,
2857 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2858 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002859 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002860 asyncResp->res.jsonValue["Name"] = "system";
2861 asyncResp->res.jsonValue["Id"] = "system";
2862 asyncResp->res.jsonValue["SystemType"] = "Physical";
2863 asyncResp->res.jsonValue["Description"] = "Computer System";
2864 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2865 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2866 "Disabled";
2867 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2868 uint64_t(0);
2869 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2870 "Disabled";
2871 asyncResp->res.jsonValue["@odata.id"] =
2872 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002873
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874 asyncResp->res.jsonValue["Processors"] = {
2875 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2876 asyncResp->res.jsonValue["Memory"] = {
2877 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2878 asyncResp->res.jsonValue["Storage"] = {
2879 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002880
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002881 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2882 {"target",
2883 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2884 {"@Redfish.ActionInfo",
2885 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002886
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002887 asyncResp->res.jsonValue["LogServices"] = {
2888 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002889
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002890 asyncResp->res.jsonValue["Bios"] = {
2891 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002892
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002893 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2894 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002895
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002896 asyncResp->res.jsonValue["Status"] = {
2897 {"Health", "OK"},
2898 {"State", "Enabled"},
2899 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002900
2901 // Fill in SerialConsole info
2902 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2903 15;
2904 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2905 {"ServiceEnabled", true},
2906 };
2907 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2908 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2909 {"ServiceEnabled", true},
2910 {"Port", 2200},
2911 // https://github.com/openbmc/docs/blob/master/console.md
2912 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2913 };
2914
2915#ifdef BMCWEB_ENABLE_KVM
2916 // Fill in GraphicalConsole info
2917 asyncResp->res.jsonValue["GraphicalConsole"] = {
2918 {"ServiceEnabled", true},
2919 {"MaxConcurrentSessions", 4},
2920 {"ConnectTypesSupported", {"KVMIP"}},
2921 };
2922#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002923 constexpr const std::array<const char*, 4> inventoryForSystems = {
2924 "xyz.openbmc_project.Inventory.Item.Dimm",
2925 "xyz.openbmc_project.Inventory.Item.Cpu",
2926 "xyz.openbmc_project.Inventory.Item.Drive",
2927 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002928
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002929 auto health = std::make_shared<HealthPopulate>(asyncResp);
2930 crow::connections::systemBus->async_method_call(
2931 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002932 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002933 if (ec)
2934 {
2935 // no inventory
2936 return;
2937 }
2938
Ed Tanous914e2d52022-01-07 11:38:34 -08002939 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002940 },
2941 "xyz.openbmc_project.ObjectMapper",
2942 "/xyz/openbmc_project/object_mapper",
2943 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2944 int32_t(0), inventoryForSystems);
2945
2946 health->populate();
2947
2948 getMainChassisId(
2949 asyncResp, [](const std::string& chassisId,
2950 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2951 aRsp->res.jsonValue["Links"]["Chassis"] = {
2952 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2953 });
2954
2955 getLocationIndicatorActive(asyncResp);
2956 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2957 getIndicatorLedState(asyncResp);
2958 getComputerSystem(asyncResp, health);
2959 getHostState(asyncResp);
2960 getBootProperties(asyncResp);
2961 getBootProgress(asyncResp);
2962 getPCIeDeviceList(asyncResp, "PCIeDevices");
2963 getHostWatchdogTimer(asyncResp);
2964 getPowerRestorePolicy(asyncResp);
2965 getAutomaticRetry(asyncResp);
2966 getLastResetTime(asyncResp);
2967#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2968 getProvisioningStatus(asyncResp);
2969#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002970 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002971 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05002972 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002973 });
2974 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002975 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002976 .methods(boost::beast::http::verb::patch)(
2977 [](const crow::Request& req,
2978 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2979 std::optional<bool> locationIndicatorActive;
2980 std::optional<std::string> indicatorLed;
2981 std::optional<nlohmann::json> bootProps;
2982 std::optional<nlohmann::json> wdtTimerProps;
2983 std::optional<std::string> assetTag;
2984 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002985 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05002986 std::optional<nlohmann::json> ipsProps;
Willy Tu15ed6782021-12-14 11:03:16 -08002987 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002988 req, asyncResp->res, "IndicatorLED", indicatorLed,
2989 "LocationIndicatorActive", locationIndicatorActive,
2990 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2991 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05002992 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
2993 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07002994 {
James Feistb49ac872019-05-21 15:12:01 -07002995 return;
2996 }
2997
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002998 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07002999
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003000 if (assetTag)
3001 {
3002 setAssetTag(asyncResp, *assetTag);
3003 }
James Feistb49ac872019-05-21 15:12:01 -07003004
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003005 if (wdtTimerProps)
3006 {
3007 std::optional<bool> wdtEnable;
3008 std::optional<std::string> wdtTimeOutAction;
3009
3010 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3011 "FunctionEnabled", wdtEnable,
3012 "TimeoutAction", wdtTimeOutAction))
3013 {
3014 return;
3015 }
3016 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3017 }
3018
3019 if (bootProps)
3020 {
3021 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003022 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003023 std::optional<std::string> bootEnable;
3024 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003025 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003026
3027 if (!json_util::readJson(
3028 *bootProps, asyncResp->res,
3029 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003030 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003031 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003032 "AutomaticRetryConfig", automaticRetryConfig,
3033 "TrustedModuleRequiredToBoot",
3034 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003035 {
3036 return;
3037 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003038
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003039 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003040 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003041 setBootProperties(asyncResp, bootSource, bootType,
3042 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003043 }
3044 if (automaticRetryConfig)
3045 {
3046 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3047 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003048
3049 if (trustedModuleRequiredToBoot)
3050 {
3051 setTrustedModuleRequiredToBoot(
3052 asyncResp, *trustedModuleRequiredToBoot);
3053 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003054 }
3055
3056 if (locationIndicatorActive)
3057 {
3058 setLocationIndicatorActive(asyncResp,
3059 *locationIndicatorActive);
3060 }
3061
3062 // TODO (Gunnar): Remove IndicatorLED after enough time has
3063 // passed
3064 if (indicatorLed)
3065 {
3066 setIndicatorLedState(asyncResp, *indicatorLed);
3067 asyncResp->res.addHeader(
3068 boost::beast::http::field::warning,
3069 "299 - \"IndicatorLED is deprecated. Use "
3070 "LocationIndicatorActive instead.\"");
3071 }
3072
3073 if (powerRestorePolicy)
3074 {
3075 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3076 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003077
3078 if (powerMode)
3079 {
3080 setPowerMode(asyncResp, *powerMode);
3081 }
Chris Cain37bbf982021-09-20 10:53:09 -05003082
3083 if (ipsProps)
3084 {
3085 std::optional<bool> ipsEnable;
3086 std::optional<uint8_t> ipsEnterUtil;
3087 std::optional<uint64_t> ipsEnterTime;
3088 std::optional<uint8_t> ipsExitUtil;
3089 std::optional<uint64_t> ipsExitTime;
3090
3091 if (!json_util::readJson(
3092 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3093 "EnterUtilizationPercent", ipsEnterUtil,
3094 "EnterDwellTimeSeconds", ipsEnterTime,
3095 "ExitUtilizationPercent", ipsExitUtil,
3096 "ExitDwellTimeSeconds", ipsExitTime))
3097 {
3098 return;
3099 }
3100 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3101 ipsEnterTime, ipsExitUtil, ipsExitTime);
3102 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003103 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003104}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303105
3106/**
3107 * SystemResetActionInfo derived class for delivering Computer Systems
3108 * ResetType AllowableValues using ResetInfo schema.
3109 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003110inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303111{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303112
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303113 /**
3114 * Functions triggers appropriate requests on DBus
3115 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003116 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003117 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003118 .methods(boost::beast::http::verb::get)(
3119 [](const crow::Request&,
3120 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3121 asyncResp->res.jsonValue = {
3122 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3123 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3124 {"Name", "Reset Action Info"},
3125 {"Id", "ResetActionInfo"},
3126 {"Parameters",
3127 {{{"Name", "ResetType"},
3128 {"Required", true},
3129 {"DataType", "String"},
3130 {"AllowableValues",
3131 {"On", "ForceOff", "ForceOn", "ForceRestart",
3132 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3133 "Nmi"}}}}}};
3134 });
3135}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003136} // namespace redfish