blob: 4a05452e5514b5aaeee2efd62b85b4ec82bdeda1 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070022#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080023#include "redfish_util.hpp"
24
John Edward Broadbent7e860f12021-04-08 15:57:16 -070025#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070026#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080027#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070028#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070029#include <sdbusplus/asio/property.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030#include <utils/json_utils.hpp>
Willy Tueee00132022-06-14 14:53:17 -070031#include <utils/sw_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
Ed Tanousabf2add2019-01-22 16:40:12 -080033#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020034
Ed Tanous1abe55e2018-09-05 08:30:59 -070035namespace redfish
36{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020037
Alpana Kumari9d3ae102019-04-12 06:49:32 -050038/**
39 * @brief Updates the Functional State of DIMMs
40 *
41 * @param[in] aResp Shared pointer for completing asynchronous calls
42 * @param[in] dimmState Dimm's Functional state, true/false
43 *
44 * @return None.
45 */
zhanghch058d1b46d2021-04-01 11:18:24 +080046inline void
47 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070048 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070050 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050051
Gunnar Mills4e0453b2020-07-08 14:00:30 -050052 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050053 // Update STATE only if previous State was DISABLED and current Dimm is
54 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070055 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050056 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
57 if (prevMemSummary == "Disabled")
58 {
Ed Tanouse05aec52022-01-25 10:28:56 -080059 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050060 {
61 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
62 "Enabled";
63 }
64 }
65}
66
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050067/*
68 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
69 *
70 * @param[in] aResp Shared pointer for completing asynchronous calls
71 * @param[in] cpuPresenceState CPU present or not
72 *
73 * @return None.
74 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070075inline void
76 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
77 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050078{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070079 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050080
Ed Tanous55f79e62022-01-25 11:26:16 -080081 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050082 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050083 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080084 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080085 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050086 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080087 if (procCountPtr != nullptr)
88 {
89 // shouldn't be possible to be nullptr
90 *procCountPtr += 1;
91 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093}
94
95/*
96 * @brief Update "ProcessorSummary" "Status" "State" based on
97 * CPU Functional State
98 *
99 * @param[in] aResp Shared pointer for completing asynchronous calls
100 * @param[in] cpuFunctionalState is CPU functional true/false
101 *
102 * @return None.
103 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700104inline void
105 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
106 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500107{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700108 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500109
Ed Tanous02cad962022-06-30 16:50:15 -0700110 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500111 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
112
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500113 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114 // Update STATE only if previous State was Non_Functional and current CPU is
115 // Functional.
116 if (prevProcState == "Disabled")
117 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800118 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500119 {
120 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
121 "Enabled";
122 }
123 }
124}
125
Ed Tanousb9d36b42022-02-26 21:42:46 -0800126inline void
127 getProcessorProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
128 const std::string& service, const std::string& path,
129 const dbus::utility::DBusPropertiesMap& properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
Ed Tanouse662eae2022-01-25 10:39:19 -0800179 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500180 {
181 messages::internalError(aResp->res);
182 return;
183 }
184
185 nlohmann::json& coreCount =
186 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
187 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
188
189 if (coreCountPtr == nullptr)
190 {
Krzysztof Grobelnya6669022022-08-10 10:11:11 +0200191 coreCount = *coreCountVal;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500192 }
193 else
194 {
195 *coreCountPtr += *coreCountVal;
196 }
197 }
198 }
199}
200
201/*
202 * @brief Get ProcessorSummary fields
203 *
204 * @param[in] aResp Shared pointer for completing asynchronous calls
205 * @param[in] service dbus service for Cpu Information
206 * @param[in] path dbus path for Cpu
207 *
208 * @return None.
209 */
210inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 const std::string& service,
212 const std::string& path)
213{
214
215 crow::connections::systemBus->async_method_call(
216 [aResp, service,
217 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800218 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700219 if (ec2)
220 {
221 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
222 messages::internalError(aResp->res);
223 return;
224 }
225 getProcessorProperties(aResp, service, path, properties);
Ali Ahmed03fbed92021-09-03 02:33:43 -0500226 },
227 service, path, "org.freedesktop.DBus.Properties", "GetAll",
228 "xyz.openbmc_project.Inventory.Item.Cpu");
229}
230
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500231/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700232 * @brief Retrieves computer system properties over dbus
233 *
234 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500235 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700236 *
237 * @return None.
238 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700239inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800240 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700241 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700242{
Ed Tanous6c34de42018-08-29 13:37:36 -0700243 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500244
Ed Tanous6c34de42018-08-29 13:37:36 -0700245 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800246 [aResp,
247 systemHealth](const boost::system::error_code ec,
248 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700249 if (ec)
250 {
251 BMCWEB_LOG_DEBUG << "DBUS response error";
252 messages::internalError(aResp->res);
253 return;
254 }
255 // Iterate over all retrieved ObjectPaths.
256 for (const std::pair<
257 std::string,
258 std::vector<std::pair<std::string, std::vector<std::string>>>>&
259 object : subtree)
260 {
261 const std::string& path = object.first;
262 BMCWEB_LOG_DEBUG << "Got path: " << path;
263 const std::vector<std::pair<std::string, std::vector<std::string>>>&
264 connectionNames = object.second;
265 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700267 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700268 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700269
270 auto memoryHealth = std::make_shared<HealthPopulate>(
271 aResp, "/MemorySummary/Status"_json_pointer);
272
273 auto cpuHealth = std::make_shared<HealthPopulate>(
274 aResp, "/ProcessorSummary/Status"_json_pointer);
275
276 systemHealth->children.emplace_back(memoryHealth);
277 systemHealth->children.emplace_back(cpuHealth);
278
279 // This is not system, so check if it's cpu, dimm, UUID or
280 // BiosVer
281 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700282 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700283 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700284 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700285 if (interfaceName ==
286 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700287 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700288 BMCWEB_LOG_DEBUG
289 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500290
Ed Tanous002d39b2022-05-31 08:59:27 -0700291 crow::connections::systemBus->async_method_call(
292 [aResp, service{connection.first},
293 path](const boost::system::error_code ec2,
294 const dbus::utility::DBusPropertiesMap&
295 properties) {
296 if (ec2)
297 {
298 BMCWEB_LOG_ERROR << "DBUS response error "
299 << ec2;
300 messages::internalError(aResp->res);
301 return;
302 }
303 BMCWEB_LOG_DEBUG << "Got " << properties.size()
304 << " Dimm properties.";
305
306 if (!properties.empty())
307 {
308 for (const std::pair<
309 std::string,
310 dbus::utility::DbusVariantType>&
311 property : properties)
312 {
313 if (property.first != "MemorySizeInKB")
Ed Tanous029573d2019-02-01 10:57:49 -0800314 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700315 continue;
Ed Tanous029573d2019-02-01 10:57:49 -0800316 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700317 const uint32_t* value =
318 std::get_if<uint32_t>(&property.second);
319 if (value == nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800320 {
321 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -0700322 << "Find incorrect type of MemorySize";
323 continue;
324 }
325 nlohmann::json& totalMemory =
326 aResp->res
327 .jsonValue["MemorySummary"]
328 ["TotalSystemMemoryGiB"];
Ed Tanous02cad962022-06-30 16:50:15 -0700329 const uint64_t* preValue =
330 totalMemory.get_ptr<const uint64_t*>();
Ed Tanous002d39b2022-05-31 08:59:27 -0700331 if (preValue == nullptr)
332 {
333 continue;
334 }
335 aResp->res
336 .jsonValue["MemorySummary"]
337 ["TotalSystemMemoryGiB"] =
338 *value / (1024 * 1024) + *preValue;
339 aResp->res.jsonValue["MemorySummary"]
340 ["Status"]["State"] =
341 "Enabled";
342 }
343 }
344 else
345 {
346 sdbusplus::asio::getProperty<bool>(
347 *crow::connections::systemBus, service,
348 path,
349 "xyz.openbmc_project.State."
350 "Decorator.OperationalStatus",
351 "Functional",
352 [aResp](const boost::system::error_code ec3,
353 bool dimmState) {
354 if (ec3)
355 {
356 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000357 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800358 return;
359 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700360 updateDimmProperties(aResp, dimmState);
361 });
362 }
363 },
364 connection.first, path,
365 "org.freedesktop.DBus.Properties", "GetAll",
366 "xyz.openbmc_project.Inventory.Item.Dimm");
367
368 memoryHealth->inventory.emplace_back(path);
369 }
370 else if (interfaceName ==
371 "xyz.openbmc_project.Inventory.Item.Cpu")
372 {
373 BMCWEB_LOG_DEBUG
374 << "Found Cpu, now get its properties.";
375
376 getProcessorSummary(aResp, connection.first, path);
377
378 cpuHealth->inventory.emplace_back(path);
379 }
380 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
381 {
382 BMCWEB_LOG_DEBUG
383 << "Found UUID, now get its properties.";
384 crow::connections::systemBus->async_method_call(
385 [aResp](const boost::system::error_code ec3,
386 const dbus::utility::DBusPropertiesMap&
387 properties) {
388 if (ec3)
389 {
390 BMCWEB_LOG_DEBUG << "DBUS response error "
391 << ec3;
392 messages::internalError(aResp->res);
393 return;
394 }
395 BMCWEB_LOG_DEBUG << "Got " << properties.size()
396 << " UUID properties.";
397 for (const std::pair<
398 std::string,
399 dbus::utility::DbusVariantType>& property :
400 properties)
401 {
402 if (property.first == "UUID")
403 {
404 const std::string* value =
405 std::get_if<std::string>(
406 &property.second);
407
408 if (value != nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800409 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700410 std::string valueStr = *value;
411 if (valueStr.size() == 32)
Ed Tanous029573d2019-02-01 10:57:49 -0800412 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700413 valueStr.insert(8, 1, '-');
414 valueStr.insert(13, 1, '-');
415 valueStr.insert(18, 1, '-');
416 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700417 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700418 BMCWEB_LOG_DEBUG << "UUID = "
419 << valueStr;
420 aResp->res.jsonValue["UUID"] = valueStr;
Ed Tanous029573d2019-02-01 10:57:49 -0800421 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700422 }
423 }
424 },
425 connection.first, path,
426 "org.freedesktop.DBus.Properties", "GetAll",
427 "xyz.openbmc_project.Common.UUID");
428 }
429 else if (interfaceName ==
430 "xyz.openbmc_project.Inventory.Item.System")
431 {
432 crow::connections::systemBus->async_method_call(
433 [aResp](const boost::system::error_code ec2,
434 const dbus::utility::DBusPropertiesMap&
435 propertiesList) {
436 if (ec2)
437 {
438 // doesn't have to include this
439 // interface
440 return;
441 }
442 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
443 << " properties for system";
444 for (const std::pair<
445 std::string,
446 dbus::utility::DbusVariantType>& property :
447 propertiesList)
448 {
449 const std::string& propertyName =
450 property.first;
451 if ((propertyName == "PartNumber") ||
452 (propertyName == "SerialNumber") ||
453 (propertyName == "Manufacturer") ||
454 (propertyName == "Model") ||
455 (propertyName == "SubModel"))
456 {
457 const std::string* value =
458 std::get_if<std::string>(
459 &property.second);
460 if (value != nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800461 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700462 aResp->res.jsonValue[propertyName] =
463 *value;
Ed Tanous029573d2019-02-01 10:57:49 -0800464 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700465 }
466 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500467
Ed Tanous002d39b2022-05-31 08:59:27 -0700468 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700469 sw_util::populateSoftwareInformation(
470 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700471 false);
472 },
473 connection.first, path,
474 "org.freedesktop.DBus.Properties", "GetAll",
475 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700476
Ed Tanous002d39b2022-05-31 08:59:27 -0700477 sdbusplus::asio::getProperty<std::string>(
478 *crow::connections::systemBus, connection.first,
479 path,
480 "xyz.openbmc_project.Inventory.Decorator."
481 "AssetTag",
482 "AssetTag",
483 [aResp](const boost::system::error_code ec2,
484 const std::string& value) {
485 if (ec2)
486 {
487 // doesn't have to include this
488 // interface
489 return;
490 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700491
Ed Tanous002d39b2022-05-31 08:59:27 -0700492 aResp->res.jsonValue["AssetTag"] = value;
493 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700494 }
495 }
496 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700497 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700498 },
499 "xyz.openbmc_project.ObjectMapper",
500 "/xyz/openbmc_project/object_mapper",
501 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700502 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500503 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700504 "xyz.openbmc_project.Inventory.Decorator.Asset",
505 "xyz.openbmc_project.Inventory.Item.Cpu",
506 "xyz.openbmc_project.Inventory.Item.Dimm",
507 "xyz.openbmc_project.Inventory.Item.System",
508 "xyz.openbmc_project.Common.UUID",
509 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700510}
511
512/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700513 * @brief Retrieves host state properties over dbus
514 *
515 * @param[in] aResp Shared pointer for completing asynchronous calls.
516 *
517 * @return None.
518 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800519inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700520{
521 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700522 sdbusplus::asio::getProperty<std::string>(
523 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
524 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
525 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800526 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700527 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700528 if (ec)
529 {
530 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700531 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700532 // Service not available, no error, just don't return
533 // host state info
534 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700535 return;
536 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700537 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
538 messages::internalError(aResp->res);
539 return;
540 }
Ed Tanous66173382018-08-15 18:20:59 -0700541
Ed Tanous002d39b2022-05-31 08:59:27 -0700542 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
543 // Verify Host State
544 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
545 {
546 aResp->res.jsonValue["PowerState"] = "On";
547 aResp->res.jsonValue["Status"]["State"] = "Enabled";
548 }
549 else if (hostState ==
550 "xyz.openbmc_project.State.Host.HostState.Quiesced")
551 {
552 aResp->res.jsonValue["PowerState"] = "On";
553 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
554 }
555 else if (hostState ==
556 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
557 {
558 aResp->res.jsonValue["PowerState"] = "On";
559 aResp->res.jsonValue["Status"]["State"] = "InTest";
560 }
561 else if (
562 hostState ==
563 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
564 {
565 aResp->res.jsonValue["PowerState"] = "PoweringOn";
566 aResp->res.jsonValue["Status"]["State"] = "Starting";
567 }
568 else if (hostState ==
569 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
570 {
571 aResp->res.jsonValue["PowerState"] = "PoweringOff";
572 aResp->res.jsonValue["Status"]["State"] = "Disabled";
573 }
574 else
575 {
576 aResp->res.jsonValue["PowerState"] = "Off";
577 aResp->res.jsonValue["Status"]["State"] = "Disabled";
578 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700579 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700580}
581
582/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500583 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530584 *
585 * @param[in] dbusSource The boot source in DBUS speak.
586 *
587 * @return Returns as a string, the boot source in Redfish terms. If translation
588 * cannot be done, returns an empty string.
589 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000590inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530591{
592 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
593 {
594 return "None";
595 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700596 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530597 {
598 return "Hdd";
599 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700600 if (dbusSource ==
601 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530602 {
603 return "Cd";
604 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700605 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530606 {
607 return "Pxe";
608 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700609 if (dbusSource ==
610 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700611 {
612 return "Usb";
613 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700614 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615}
616
617/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300618 * @brief Translates boot type DBUS property value to redfish.
619 *
620 * @param[in] dbusType The boot type in DBUS speak.
621 *
622 * @return Returns as a string, the boot type in Redfish terms. If translation
623 * cannot be done, returns an empty string.
624 */
625inline std::string dbusToRfBootType(const std::string& dbusType)
626{
627 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
628 {
629 return "Legacy";
630 }
631 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
632 {
633 return "UEFI";
634 }
635 return "";
636}
637
638/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500639 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530640 *
641 * @param[in] dbusMode The boot mode in DBUS speak.
642 *
643 * @return Returns as a string, the boot mode in Redfish terms. If translation
644 * cannot be done, returns an empty string.
645 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000646inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530647{
648 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
649 {
650 return "None";
651 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700652 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530653 {
654 return "Diags";
655 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700656 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530657 {
658 return "BiosSetup";
659 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700660 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661}
662
663/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600664 * @brief Translates boot progress DBUS property value to redfish.
665 *
666 * @param[in] dbusBootProgress The boot progress in DBUS speak.
667 *
668 * @return Returns as a string, the boot progress in Redfish terms. If
669 * translation cannot be done, returns "None".
670 */
671inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
672{
673 // Now convert the D-Bus BootProgress to the appropriate Redfish
674 // enum
675 std::string rfBpLastState = "None";
676 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
677 "ProgressStages.Unspecified")
678 {
679 rfBpLastState = "None";
680 }
681 else if (dbusBootProgress ==
682 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
683 "PrimaryProcInit")
684 {
685 rfBpLastState = "PrimaryProcessorInitializationStarted";
686 }
687 else if (dbusBootProgress ==
688 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
689 "BusInit")
690 {
691 rfBpLastState = "BusInitializationStarted";
692 }
693 else if (dbusBootProgress ==
694 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
695 "MemoryInit")
696 {
697 rfBpLastState = "MemoryInitializationStarted";
698 }
699 else if (dbusBootProgress ==
700 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
701 "SecondaryProcInit")
702 {
703 rfBpLastState = "SecondaryProcessorInitializationStarted";
704 }
705 else if (dbusBootProgress ==
706 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
707 "PCIInit")
708 {
709 rfBpLastState = "PCIResourceConfigStarted";
710 }
711 else if (dbusBootProgress ==
712 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
713 "SystemSetup")
714 {
715 rfBpLastState = "SetupEntered";
716 }
717 else if (dbusBootProgress ==
718 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
719 "SystemInitComplete")
720 {
721 rfBpLastState = "SystemHardwareInitializationComplete";
722 }
723 else if (dbusBootProgress ==
724 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
725 "OSStart")
726 {
727 rfBpLastState = "OSBootStarted";
728 }
729 else if (dbusBootProgress ==
730 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
731 "OSRunning")
732 {
733 rfBpLastState = "OSRunning";
734 }
735 else
736 {
737 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
738 << dbusBootProgress;
739 // Just return the default
740 }
741 return rfBpLastState;
742}
743
744/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500745 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530746 *
747 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700748 * @param[out] bootSource The DBus source
749 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530750 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700751 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530752 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800753inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500754 const std::string& rfSource,
755 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530756{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300757 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
758 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700759
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530760 if (rfSource == "None")
761 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700762 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530763 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700764 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530765 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
767 }
768 else if (rfSource == "Hdd")
769 {
770 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
771 }
772 else if (rfSource == "Diags")
773 {
774 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
775 }
776 else if (rfSource == "Cd")
777 {
778 bootSource =
779 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
780 }
781 else if (rfSource == "BiosSetup")
782 {
783 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700785 else if (rfSource == "Usb")
786 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787 bootSource =
788 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700789 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530790 else
791 {
George Liu0fda0f12021-11-16 10:06:17 +0800792 BMCWEB_LOG_DEBUG
793 << "Invalid property value for BootSourceOverrideTarget: "
794 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700795 messages::propertyValueNotInList(aResp->res, rfSource,
796 "BootSourceTargetOverride");
797 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530798 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700799 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530800}
Ali Ahmed19817712021-06-29 17:01:52 -0500801
Andrew Geissler978b8802020-11-19 13:36:40 -0600802/**
803 * @brief Retrieves boot progress of the system
804 *
805 * @param[in] aResp Shared pointer for generating response message.
806 *
807 * @return None.
808 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800809inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600810{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700811 sdbusplus::asio::getProperty<std::string>(
812 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
813 "/xyz/openbmc_project/state/host0",
814 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600815 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700816 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700817 if (ec)
818 {
819 // BootProgress is an optional object so just do nothing if
820 // not found
821 return;
822 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600823
Ed Tanous002d39b2022-05-31 08:59:27 -0700824 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600825
Ed Tanous002d39b2022-05-31 08:59:27 -0700826 aResp->res.jsonValue["BootProgress"]["LastState"] =
827 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700828 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600829}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530830
831/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300832 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300833 *
834 * @param[in] aResp Shared pointer for generating response message.
835 *
836 * @return None.
837 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300838
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300839inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300840{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700841 sdbusplus::asio::getProperty<std::string>(
842 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
843 "/xyz/openbmc_project/control/host0/boot",
844 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300845 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700846 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700847 if (ec)
848 {
849 // not an error, don't have to have the interface
850 return;
851 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300852
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300854
Ed Tanous002d39b2022-05-31 08:59:27 -0700855 aResp->res.jsonValue["Boot"]
856 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
857 {"Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300858
Ed Tanous002d39b2022-05-31 08:59:27 -0700859 auto rfType = dbusToRfBootType(bootType);
860 if (rfType.empty())
861 {
862 messages::internalError(aResp->res);
863 return;
864 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300865
Ed Tanous002d39b2022-05-31 08:59:27 -0700866 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700867 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868}
869
870/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300871 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530872 *
873 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530874 *
875 * @return None.
876 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300877
878inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530879{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700880 sdbusplus::asio::getProperty<std::string>(
881 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
882 "/xyz/openbmc_project/control/host0/boot",
883 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300884 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700885 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700886 if (ec)
887 {
888 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
889 messages::internalError(aResp->res);
890 return;
891 }
892
893 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
894
895 aResp->res
896 .jsonValue["Boot"]
897 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
898 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
899
900 if (bootModeStr !=
901 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
902 {
903 auto rfMode = dbusToRfBootMode(bootModeStr);
904 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530905 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700906 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
907 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700909 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700910 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530911}
912
913/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300914 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 *
916 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530917 *
918 * @return None.
919 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300920
921inline void
922 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700924 sdbusplus::asio::getProperty<std::string>(
925 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
926 "/xyz/openbmc_project/control/host0/boot",
927 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300928 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700929 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700930 if (ec)
931 {
932 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000933 if (ec.value() == boost::asio::error::host_unreachable)
934 {
935 return;
936 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700937 messages::internalError(aResp->res);
938 return;
939 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940
Ed Tanous002d39b2022-05-31 08:59:27 -0700941 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530942
Ed Tanous002d39b2022-05-31 08:59:27 -0700943 auto rfSource = dbusToRfBootSource(bootSourceStr);
944 if (!rfSource.empty())
945 {
946 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
947 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300948
Ed Tanous002d39b2022-05-31 08:59:27 -0700949 // Get BootMode as BootSourceOverrideTarget is constructed
950 // from both BootSource and BootMode
951 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700952 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530953}
954
955/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300956 * @brief This functions abstracts all the logic behind getting a
957 * "BootSourceOverrideEnabled" property from an overall boot override enable
958 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 *
960 * @param[in] aResp Shared pointer for generating response message.
961 *
962 * @return None.
963 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530964
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300965inline void
966 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
967 const bool bootOverrideEnableSetting)
968{
969 if (!bootOverrideEnableSetting)
970 {
971 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
972 return;
973 }
974
975 // If boot source override is enabled, we need to check 'one_time'
976 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700977 sdbusplus::asio::getProperty<bool>(
978 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
979 "/xyz/openbmc_project/control/host0/boot/one_time",
980 "xyz.openbmc_project.Object.Enable", "Enabled",
981 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700982 if (ec)
983 {
984 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
985 messages::internalError(aResp->res);
986 return;
987 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530988
Ed Tanous002d39b2022-05-31 08:59:27 -0700989 if (oneTimeSetting)
990 {
991 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
992 }
993 else
994 {
995 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
996 "Continuous";
997 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700998 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530999}
1000
1001/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001002 * @brief Retrieves boot override enable over DBUS
1003 *
1004 * @param[in] aResp Shared pointer for generating response message.
1005 *
1006 * @return None.
1007 */
1008
1009inline void
1010 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1011{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001012 sdbusplus::asio::getProperty<bool>(
1013 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1014 "/xyz/openbmc_project/control/host0/boot",
1015 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001016 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001017 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001018 if (ec)
1019 {
1020 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001021 if (ec.value() == boost::asio::error::host_unreachable)
1022 {
1023 return;
1024 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001025 messages::internalError(aResp->res);
1026 return;
1027 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001028
Ed Tanous002d39b2022-05-31 08:59:27 -07001029 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001030 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001031}
1032
1033/**
1034 * @brief Retrieves boot source override properties
1035 *
1036 * @param[in] aResp Shared pointer for generating response message.
1037 *
1038 * @return None.
1039 */
1040inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1041{
1042 BMCWEB_LOG_DEBUG << "Get boot information.";
1043
1044 getBootOverrideSource(aResp);
1045 getBootOverrideType(aResp);
1046 getBootOverrideEnable(aResp);
1047}
1048
1049/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001050 * @brief Retrieves the Last Reset Time
1051 *
1052 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1053 * and power off. Even though this is the "system" Redfish object look at the
1054 * chassis D-Bus interface for the LastStateChangeTime since this has the
1055 * last power operation time.
1056 *
1057 * @param[in] aResp Shared pointer for generating response message.
1058 *
1059 * @return None.
1060 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001061inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001062{
1063 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1064
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001065 sdbusplus::asio::getProperty<uint64_t>(
1066 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1067 "/xyz/openbmc_project/state/chassis0",
1068 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1069 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001070 if (ec)
1071 {
1072 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1073 return;
1074 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001075
Ed Tanous002d39b2022-05-31 08:59:27 -07001076 // LastStateChangeTime is epoch time, in milliseconds
1077 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1078 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001079
Ed Tanous002d39b2022-05-31 08:59:27 -07001080 // Convert to ISO 8601 standard
1081 aResp->res.jsonValue["LastResetTime"] =
1082 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001083 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001084}
1085
1086/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001087 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1088 *
1089 * @param[in] aResp Shared pointer for generating response message.
1090 *
1091 * @return None.
1092 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001093inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001094{
1095 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1096
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001097 sdbusplus::asio::getProperty<bool>(
1098 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1099 "/xyz/openbmc_project/control/host0/auto_reboot",
1100 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1101 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001102 if (ec)
1103 {
1104 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1105 return;
1106 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001107
Ed Tanous002d39b2022-05-31 08:59:27 -07001108 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1109 if (autoRebootEnabled)
1110 {
1111 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1112 "RetryAttempts";
1113 // If AutomaticRetry (AutoReboot) is enabled see how many
1114 // attempts are left
1115 sdbusplus::asio::getProperty<uint32_t>(
1116 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1117 "/xyz/openbmc_project/state/host0",
1118 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1119 "AttemptsLeft",
1120 [aResp](const boost::system::error_code ec2,
1121 const uint32_t autoRebootAttemptsLeft) {
1122 if (ec2)
1123 {
1124 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1125 return;
1126 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001127
Ed Tanous002d39b2022-05-31 08:59:27 -07001128 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1129 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001130
Ed Tanous002d39b2022-05-31 08:59:27 -07001131 aResp->res
1132 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1133 autoRebootAttemptsLeft;
1134 });
1135 }
1136 else
1137 {
1138 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1139 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001140
Ed Tanous002d39b2022-05-31 08:59:27 -07001141 // Not on D-Bus. Hardcoded here:
1142 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1143 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001144
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1146 // and RetryAttempts. OpenBMC only supports Disabled and
1147 // RetryAttempts.
1148 aResp->res.jsonValue["Boot"]
1149 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1150 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001151 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001152}
1153
1154/**
George Liuc6a620f2020-04-10 17:18:11 +08001155 * @brief Retrieves power restore policy over DBUS.
1156 *
1157 * @param[in] aResp Shared pointer for generating response message.
1158 *
1159 * @return None.
1160 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001161inline void
1162 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001163{
1164 BMCWEB_LOG_DEBUG << "Get power restore policy";
1165
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001166 sdbusplus::asio::getProperty<std::string>(
1167 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1168 "/xyz/openbmc_project/control/host0/power_restore_policy",
1169 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1170 [aResp](const boost::system::error_code ec, const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001171 if (ec)
1172 {
1173 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1174 return;
1175 }
George Liuc6a620f2020-04-10 17:18:11 +08001176
Ed Tanous002d39b2022-05-31 08:59:27 -07001177 const boost::container::flat_map<std::string, std::string> policyMaps = {
1178 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1179 "AlwaysOn"},
1180 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1181 "AlwaysOff"},
1182 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1183 "LastState"},
1184 // Return `AlwaysOff` when power restore policy set to "None"
1185 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1186 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001187
Ed Tanous002d39b2022-05-31 08:59:27 -07001188 auto policyMapsIt = policyMaps.find(policy);
1189 if (policyMapsIt == policyMaps.end())
1190 {
1191 messages::internalError(aResp->res);
1192 return;
1193 }
George Liuc6a620f2020-04-10 17:18:11 +08001194
Ed Tanous002d39b2022-05-31 08:59:27 -07001195 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001196 });
George Liuc6a620f2020-04-10 17:18:11 +08001197}
1198
1199/**
Ali Ahmed19817712021-06-29 17:01:52 -05001200 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1201 * TPM is required for booting the host.
1202 *
1203 * @param[in] aResp Shared pointer for generating response message.
1204 *
1205 * @return None.
1206 */
1207inline void getTrustedModuleRequiredToBoot(
1208 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1209{
1210 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1211
1212 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001213 [aResp](const boost::system::error_code ec,
1214 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001215 if (ec)
1216 {
1217 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1218 << ec;
1219 // This is an optional D-Bus object so just return if
1220 // error occurs
1221 return;
1222 }
1223 if (subtree.empty())
1224 {
1225 // As noted above, this is an optional interface so just return
1226 // if there is no instance found
1227 return;
1228 }
1229
1230 /* When there is more than one TPMEnable object... */
1231 if (subtree.size() > 1)
1232 {
1233 BMCWEB_LOG_DEBUG
1234 << "DBUS response has more than 1 TPM Enable object:"
1235 << subtree.size();
1236 // Throw an internal Error and return
1237 messages::internalError(aResp->res);
1238 return;
1239 }
1240
1241 // Make sure the Dbus response map has a service and objectPath
1242 // field
1243 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1244 {
1245 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1246 messages::internalError(aResp->res);
1247 return;
1248 }
1249
1250 const std::string& path = subtree[0].first;
1251 const std::string& serv = subtree[0].second.begin()->first;
1252
1253 // Valid TPM Enable object found, now reading the current value
1254 sdbusplus::asio::getProperty<bool>(
1255 *crow::connections::systemBus, serv, path,
1256 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous8a592812022-06-04 09:06:59 -07001257 [aResp](const boost::system::error_code ec2, bool tpmRequired) {
1258 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001259 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001260 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001261 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001262 messages::internalError(aResp->res);
1263 return;
1264 }
1265
Ed Tanous002d39b2022-05-31 08:59:27 -07001266 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001267 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001268 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1269 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001270 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001271 else
1272 {
1273 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1274 "Disabled";
1275 }
1276 });
Ali Ahmed19817712021-06-29 17:01:52 -05001277 },
1278 "xyz.openbmc_project.ObjectMapper",
1279 "/xyz/openbmc_project/object_mapper",
1280 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1281 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1282}
1283
1284/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001285 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1286 * TPM is required for booting the host.
1287 *
1288 * @param[in] aResp Shared pointer for generating response message.
1289 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1290 *
1291 * @return None.
1292 */
1293inline void setTrustedModuleRequiredToBoot(
1294 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1295{
1296 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1297
1298 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001299 [aResp, tpmRequired](const boost::system::error_code ec,
1300 dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001301 if (ec)
1302 {
1303 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1304 << ec;
1305 messages::internalError(aResp->res);
1306 return;
1307 }
1308 if (subtree.empty())
1309 {
1310 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1311 "TrustedModuleRequiredToBoot");
1312 return;
1313 }
1314
1315 /* When there is more than one TPMEnable object... */
1316 if (subtree.size() > 1)
1317 {
1318 BMCWEB_LOG_DEBUG
1319 << "DBUS response has more than 1 TPM Enable object:"
1320 << subtree.size();
1321 // Throw an internal Error and return
1322 messages::internalError(aResp->res);
1323 return;
1324 }
1325
1326 // Make sure the Dbus response map has a service and objectPath
1327 // field
1328 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1329 {
1330 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1331 messages::internalError(aResp->res);
1332 return;
1333 }
1334
1335 const std::string& path = subtree[0].first;
1336 const std::string& serv = subtree[0].second.begin()->first;
1337
1338 if (serv.empty())
1339 {
1340 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1341 messages::internalError(aResp->res);
1342 return;
1343 }
1344
1345 // Valid TPM Enable object found, now setting the value
1346 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07001347 [aResp](const boost::system::error_code ec2) {
1348 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001349 {
1350 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001351 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001352 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001353 messages::internalError(aResp->res);
1354 return;
1355 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001356 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1357 },
1358 serv, path, "org.freedesktop.DBus.Properties", "Set",
1359 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1360 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001361 },
1362 "xyz.openbmc_project.ObjectMapper",
1363 "/xyz/openbmc_project/object_mapper",
1364 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1365 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1366}
1367
1368/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301369 * @brief Sets boot properties into DBUS object(s).
1370 *
1371 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001372 * @param[in] bootType The boot type to set.
1373 * @return Integer error code.
1374 */
1375inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001376 const std::optional<std::string>& bootType)
1377{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001378 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001379
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001380 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001381 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001382 return;
1383 }
1384
1385 // Source target specified
1386 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1387 // Figure out which DBUS interface and property to use
1388 if (*bootType == "Legacy")
1389 {
1390 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1391 }
1392 else if (*bootType == "UEFI")
1393 {
1394 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1395 }
1396 else
1397 {
1398 BMCWEB_LOG_DEBUG << "Invalid property value for "
1399 "BootSourceOverrideMode: "
1400 << *bootType;
1401 messages::propertyValueNotInList(aResp->res, *bootType,
1402 "BootSourceOverrideMode");
1403 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001404 }
1405
1406 // Act on validated parameters
1407 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1408
1409 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001410 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001411 if (ec)
1412 {
1413 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1414 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001415 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001416 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001417 return;
1418 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001419 messages::internalError(aResp->res);
1420 return;
1421 }
1422 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001423 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001424 "xyz.openbmc_project.Settings",
1425 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001426 "org.freedesktop.DBus.Properties", "Set",
1427 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001428 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001429}
1430
1431/**
1432 * @brief Sets boot properties into DBUS object(s).
1433 *
1434 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001435 * @param[in] bootType The boot type to set.
1436 * @return Integer error code.
1437 */
1438inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1439 const std::optional<std::string>& bootEnable)
1440{
1441 if (!bootEnable)
1442 {
1443 return;
1444 }
1445 // Source target specified
1446 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1447
1448 bool bootOverrideEnable = false;
1449 bool bootOverridePersistent = false;
1450 // Figure out which DBUS interface and property to use
1451 if (*bootEnable == "Disabled")
1452 {
1453 bootOverrideEnable = false;
1454 }
1455 else if (*bootEnable == "Once")
1456 {
1457 bootOverrideEnable = true;
1458 bootOverridePersistent = false;
1459 }
1460 else if (*bootEnable == "Continuous")
1461 {
1462 bootOverrideEnable = true;
1463 bootOverridePersistent = true;
1464 }
1465 else
1466 {
George Liu0fda0f12021-11-16 10:06:17 +08001467 BMCWEB_LOG_DEBUG
1468 << "Invalid property value for BootSourceOverrideEnabled: "
1469 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001470 messages::propertyValueNotInList(aResp->res, *bootEnable,
1471 "BootSourceOverrideEnabled");
1472 return;
1473 }
1474
1475 // Act on validated parameters
1476 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1477
1478 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07001479 [aResp](const boost::system::error_code ec2) {
1480 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001481 {
Ed Tanous8a592812022-06-04 09:06:59 -07001482 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001483 messages::internalError(aResp->res);
1484 return;
1485 }
1486 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001487 },
1488 "xyz.openbmc_project.Settings",
1489 "/xyz/openbmc_project/control/host0/boot",
1490 "org.freedesktop.DBus.Properties", "Set",
1491 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001492 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001493
1494 if (!bootOverrideEnable)
1495 {
1496 return;
1497 }
1498
1499 // In case boot override is enabled we need to set correct value for the
1500 // 'one_time' enable DBus interface
1501 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1502 << bootOverridePersistent;
1503
1504 crow::connections::systemBus->async_method_call(
1505 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001506 if (ec)
1507 {
1508 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1509 messages::internalError(aResp->res);
1510 return;
1511 }
1512 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001513 },
1514 "xyz.openbmc_project.Settings",
1515 "/xyz/openbmc_project/control/host0/boot/one_time",
1516 "org.freedesktop.DBus.Properties", "Set",
1517 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001518 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001519}
1520
1521/**
1522 * @brief Sets boot properties into DBUS object(s).
1523 *
1524 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301525 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301526 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001527 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301528 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001529inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001530 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301531{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001532 std::string bootSourceStr;
1533 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001534
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001535 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301536 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001537 return;
1538 }
1539
1540 // Source target specified
1541 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1542 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001543 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1544 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001545 {
1546 BMCWEB_LOG_DEBUG
1547 << "Invalid property value for BootSourceOverrideTarget: "
1548 << *bootSource;
1549 messages::propertyValueNotInList(aResp->res, *bootSource,
1550 "BootSourceTargetOverride");
1551 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001552 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301553
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001554 // Act on validated parameters
1555 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1556 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001557
1558 crow::connections::systemBus->async_method_call(
1559 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001560 if (ec)
1561 {
1562 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1563 messages::internalError(aResp->res);
1564 return;
1565 }
1566 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001567 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001568 "xyz.openbmc_project.Settings",
1569 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001570 "org.freedesktop.DBus.Properties", "Set",
1571 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001572 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001573
1574 crow::connections::systemBus->async_method_call(
1575 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001576 if (ec)
1577 {
1578 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1579 messages::internalError(aResp->res);
1580 return;
1581 }
1582 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001583 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001584 "xyz.openbmc_project.Settings",
1585 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001586 "org.freedesktop.DBus.Properties", "Set",
1587 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001588 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001589}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001590
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001591/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001592 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301593 *
1594 * @param[in] aResp Shared pointer for generating response message.
1595 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001596 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301597 * @param[in] bootEnable The boot override enable from incoming RF request.
1598 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001599 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301600 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001601
1602inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1603 const std::optional<std::string>& bootSource,
1604 const std::optional<std::string>& bootType,
1605 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301606{
1607 BMCWEB_LOG_DEBUG << "Set boot information.";
1608
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001609 setBootModeOrSource(aResp, bootSource);
1610 setBootType(aResp, bootType);
1611 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301612}
1613
George Liuc6a620f2020-04-10 17:18:11 +08001614/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001615 * @brief Sets AssetTag
1616 *
1617 * @param[in] aResp Shared pointer for generating response message.
1618 * @param[in] assetTag "AssetTag" from request.
1619 *
1620 * @return None.
1621 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001622inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001623 const std::string& assetTag)
1624{
1625 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001626 [aResp,
1627 assetTag](const boost::system::error_code ec,
1628 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001629 if (ec)
1630 {
1631 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1632 messages::internalError(aResp->res);
1633 return;
1634 }
1635 if (subtree.empty())
1636 {
1637 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1638 messages::internalError(aResp->res);
1639 return;
1640 }
1641 // Assume only 1 system D-Bus object
1642 // Throw an error if there is more than 1
1643 if (subtree.size() > 1)
1644 {
1645 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1646 messages::internalError(aResp->res);
1647 return;
1648 }
1649 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1650 {
1651 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1652 messages::internalError(aResp->res);
1653 return;
1654 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001655
Ed Tanous002d39b2022-05-31 08:59:27 -07001656 const std::string& path = subtree[0].first;
1657 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001658
Ed Tanous002d39b2022-05-31 08:59:27 -07001659 if (service.empty())
1660 {
1661 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1662 messages::internalError(aResp->res);
1663 return;
1664 }
1665
1666 crow::connections::systemBus->async_method_call(
1667 [aResp](const boost::system::error_code ec2) {
1668 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001669 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001670 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1671 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001672 messages::internalError(aResp->res);
1673 return;
1674 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001675 },
1676 service, path, "org.freedesktop.DBus.Properties", "Set",
1677 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1678 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001679 },
1680 "xyz.openbmc_project.ObjectMapper",
1681 "/xyz/openbmc_project/object_mapper",
1682 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1683 "/xyz/openbmc_project/inventory", int32_t(0),
1684 std::array<const char*, 1>{
1685 "xyz.openbmc_project.Inventory.Item.System"});
1686}
1687
1688/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001689 * @brief Sets automaticRetry (Auto Reboot)
1690 *
1691 * @param[in] aResp Shared pointer for generating response message.
1692 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1693 *
1694 * @return None.
1695 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001696inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001697 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001698{
1699 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1700
1701 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001702 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001703
1704 if (automaticRetryConfig == "Disabled")
1705 {
1706 autoRebootEnabled = false;
1707 }
1708 else if (automaticRetryConfig == "RetryAttempts")
1709 {
1710 autoRebootEnabled = true;
1711 }
1712 else
1713 {
George Liu0fda0f12021-11-16 10:06:17 +08001714 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001715 << automaticRetryConfig;
1716 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1717 "AutomaticRetryConfig");
1718 return;
1719 }
1720
1721 crow::connections::systemBus->async_method_call(
1722 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001723 if (ec)
1724 {
1725 messages::internalError(aResp->res);
1726 return;
1727 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001728 },
1729 "xyz.openbmc_project.Settings",
1730 "/xyz/openbmc_project/control/host0/auto_reboot",
1731 "org.freedesktop.DBus.Properties", "Set",
1732 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001733 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001734}
1735
1736/**
George Liuc6a620f2020-04-10 17:18:11 +08001737 * @brief Sets power restore policy properties.
1738 *
1739 * @param[in] aResp Shared pointer for generating response message.
1740 * @param[in] policy power restore policy properties from request.
1741 *
1742 * @return None.
1743 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001744inline void
1745 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1746 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001747{
1748 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1749
1750 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001751 {"AlwaysOn",
1752 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1753 {"AlwaysOff",
1754 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1755 {"LastState",
1756 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001757
1758 std::string powerRestorPolicy;
1759
Gunnar Mills4e69c902021-01-05 19:50:11 -06001760 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001761 if (policyMapsIt == policyMaps.end())
1762 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001763 messages::propertyValueNotInList(aResp->res, policy,
1764 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001765 return;
1766 }
1767
1768 powerRestorPolicy = policyMapsIt->second;
1769
1770 crow::connections::systemBus->async_method_call(
1771 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001772 if (ec)
1773 {
1774 messages::internalError(aResp->res);
1775 return;
1776 }
George Liuc6a620f2020-04-10 17:18:11 +08001777 },
1778 "xyz.openbmc_project.Settings",
1779 "/xyz/openbmc_project/control/host0/power_restore_policy",
1780 "org.freedesktop.DBus.Properties", "Set",
1781 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001782 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001783}
1784
AppaRao Pulia6349912019-10-18 17:16:08 +05301785#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1786/**
1787 * @brief Retrieves provisioning status
1788 *
1789 * @param[in] aResp Shared pointer for completing asynchronous calls.
1790 *
1791 * @return None.
1792 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001793inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301794{
1795 BMCWEB_LOG_DEBUG << "Get OEM information.";
1796 crow::connections::systemBus->async_method_call(
1797 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001798 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001799 nlohmann::json& oemPFR =
1800 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1801 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1802 "#OemComputerSystem.OpenBmc";
1803 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001804
Ed Tanous002d39b2022-05-31 08:59:27 -07001805 if (ec)
1806 {
1807 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1808 // not an error, don't have to have the interface
1809 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1810 return;
1811 }
1812
1813 const bool* provState = nullptr;
1814 const bool* lockState = nullptr;
1815 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1816 property : propertiesList)
1817 {
1818 if (property.first == "UfmProvisioned")
AppaRao Pulia6349912019-10-18 17:16:08 +05301819 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001820 provState = std::get_if<bool>(&property.second);
AppaRao Pulia6349912019-10-18 17:16:08 +05301821 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001822 else if (property.first == "UfmLocked")
AppaRao Pulia6349912019-10-18 17:16:08 +05301823 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001824 lockState = std::get_if<bool>(&property.second);
AppaRao Pulia6349912019-10-18 17:16:08 +05301825 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001826 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301827
Ed Tanous002d39b2022-05-31 08:59:27 -07001828 if ((provState == nullptr) || (lockState == nullptr))
1829 {
1830 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1831 messages::internalError(aResp->res);
1832 return;
1833 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301834
Ed Tanous002d39b2022-05-31 08:59:27 -07001835 if (*provState == true)
1836 {
1837 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301838 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001839 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301840 }
1841 else
1842 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001843 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301844 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001845 }
1846 else
1847 {
1848 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1849 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301850 },
1851 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1852 "org.freedesktop.DBus.Properties", "GetAll",
1853 "xyz.openbmc_project.PFR.Attributes");
1854}
1855#endif
1856
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301857/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001858 * @brief Translate the PowerMode to a response message.
1859 *
1860 * @param[in] aResp Shared pointer for generating response message.
1861 * @param[in] modeValue PowerMode value to be translated
1862 *
1863 * @return None.
1864 */
1865inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1866 const std::string& modeValue)
1867{
George Liu0fda0f12021-11-16 10:06:17 +08001868 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001869 {
1870 aResp->res.jsonValue["PowerMode"] = "Static";
1871 }
George Liu0fda0f12021-11-16 10:06:17 +08001872 else if (
1873 modeValue ==
1874 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001875 {
1876 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1877 }
George Liu0fda0f12021-11-16 10:06:17 +08001878 else if (modeValue ==
1879 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001880 {
1881 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1882 }
George Liu0fda0f12021-11-16 10:06:17 +08001883 else if (modeValue ==
1884 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001885 {
1886 aResp->res.jsonValue["PowerMode"] = "OEM";
1887 }
1888 else
1889 {
1890 // Any other values would be invalid
1891 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1892 messages::internalError(aResp->res);
1893 }
1894}
1895
1896/**
1897 * @brief Retrieves system power mode
1898 *
1899 * @param[in] aResp Shared pointer for generating response message.
1900 *
1901 * @return None.
1902 */
1903inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1904{
1905 BMCWEB_LOG_DEBUG << "Get power mode.";
1906
1907 // Get Power Mode object path:
1908 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001909 [aResp](const boost::system::error_code ec,
1910 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001911 if (ec)
1912 {
1913 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
1914 << ec;
1915 // This is an optional D-Bus object so just return if
1916 // error occurs
1917 return;
1918 }
1919 if (subtree.empty())
1920 {
1921 // As noted above, this is an optional interface so just return
1922 // if there is no instance found
1923 return;
1924 }
1925 if (subtree.size() > 1)
1926 {
1927 // More then one PowerMode object is not supported and is an
1928 // error
1929 BMCWEB_LOG_DEBUG
1930 << "Found more than 1 system D-Bus Power.Mode objects: "
1931 << subtree.size();
1932 messages::internalError(aResp->res);
1933 return;
1934 }
1935 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1936 {
1937 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1938 messages::internalError(aResp->res);
1939 return;
1940 }
1941 const std::string& path = subtree[0].first;
1942 const std::string& service = subtree[0].second.begin()->first;
1943 if (service.empty())
1944 {
1945 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1946 messages::internalError(aResp->res);
1947 return;
1948 }
1949 // Valid Power Mode object found, now read the current value
1950 sdbusplus::asio::getProperty<std::string>(
1951 *crow::connections::systemBus, service, path,
1952 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous8a592812022-06-04 09:06:59 -07001953 [aResp](const boost::system::error_code ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07001954 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07001955 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05001956 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001957 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07001958 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05001959 messages::internalError(aResp->res);
1960 return;
1961 }
Chris Cain3a2d04242021-05-28 16:57:10 -05001962
Ed Tanous002d39b2022-05-31 08:59:27 -07001963 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
1964 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05001965
Ed Tanous002d39b2022-05-31 08:59:27 -07001966 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1967 translatePowerMode(aResp, pmode);
1968 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001969 },
1970 "xyz.openbmc_project.ObjectMapper",
1971 "/xyz/openbmc_project/object_mapper",
1972 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1973 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1974}
1975
1976/**
1977 * @brief Validate the specified mode is valid and return the PowerMode
1978 * name associated with that string
1979 *
1980 * @param[in] aResp Shared pointer for generating response message.
1981 * @param[in] modeString String representing the desired PowerMode
1982 *
1983 * @return PowerMode value or empty string if mode is not valid
1984 */
1985inline std::string
1986 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1987 const std::string& modeString)
1988{
1989 std::string mode;
1990
1991 if (modeString == "Static")
1992 {
1993 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
1994 }
1995 else if (modeString == "MaximumPerformance")
1996 {
George Liu0fda0f12021-11-16 10:06:17 +08001997 mode =
1998 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05001999 }
2000 else if (modeString == "PowerSaving")
2001 {
2002 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2003 }
2004 else
2005 {
2006 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2007 }
2008 return mode;
2009}
2010
2011/**
2012 * @brief Sets system power mode.
2013 *
2014 * @param[in] aResp Shared pointer for generating response message.
2015 * @param[in] pmode System power mode from request.
2016 *
2017 * @return None.
2018 */
2019inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2020 const std::string& pmode)
2021{
2022 BMCWEB_LOG_DEBUG << "Set power mode.";
2023
2024 std::string powerMode = validatePowerMode(aResp, pmode);
2025 if (powerMode.empty())
2026 {
2027 return;
2028 }
2029
2030 // Get Power Mode object path:
2031 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002032 [aResp,
2033 powerMode](const boost::system::error_code ec,
2034 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002035 if (ec)
2036 {
2037 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2038 << ec;
2039 // This is an optional D-Bus object, but user attempted to patch
2040 messages::internalError(aResp->res);
2041 return;
2042 }
2043 if (subtree.empty())
2044 {
2045 // This is an optional D-Bus object, but user attempted to patch
2046 messages::resourceNotFound(aResp->res, "ComputerSystem",
2047 "PowerMode");
2048 return;
2049 }
2050 if (subtree.size() > 1)
2051 {
2052 // More then one PowerMode object is not supported and is an
2053 // error
2054 BMCWEB_LOG_DEBUG
2055 << "Found more than 1 system D-Bus Power.Mode objects: "
2056 << subtree.size();
2057 messages::internalError(aResp->res);
2058 return;
2059 }
2060 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2061 {
2062 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2063 messages::internalError(aResp->res);
2064 return;
2065 }
2066 const std::string& path = subtree[0].first;
2067 const std::string& service = subtree[0].second.begin()->first;
2068 if (service.empty())
2069 {
2070 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2071 messages::internalError(aResp->res);
2072 return;
2073 }
2074
2075 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2076 << path;
2077
2078 // Set the Power Mode property
2079 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002080 [aResp](const boost::system::error_code ec2) {
2081 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002082 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002083 messages::internalError(aResp->res);
2084 return;
2085 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002086 },
2087 service, path, "org.freedesktop.DBus.Properties", "Set",
2088 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2089 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002090 },
2091 "xyz.openbmc_project.ObjectMapper",
2092 "/xyz/openbmc_project/object_mapper",
2093 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2094 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2095}
2096
2097/**
Yong Li51709ff2019-09-30 14:13:04 +08002098 * @brief Translates watchdog timeout action DBUS property value to redfish.
2099 *
2100 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2101 *
2102 * @return Returns as a string, the timeout action in Redfish terms. If
2103 * translation cannot be done, returns an empty string.
2104 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002105inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002106{
2107 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2108 {
2109 return "None";
2110 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002111 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002112 {
2113 return "ResetSystem";
2114 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002115 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002116 {
2117 return "PowerDown";
2118 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002119 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002120 {
2121 return "PowerCycle";
2122 }
2123
2124 return "";
2125}
2126
2127/**
Yong Lic45f0082019-10-10 14:19:01 +08002128 *@brief Translates timeout action from Redfish to DBUS property value.
2129 *
2130 *@param[in] rfAction The timeout action in Redfish.
2131 *
2132 *@return Returns as a string, the time_out action as expected by DBUS.
2133 *If translation cannot be done, returns an empty string.
2134 */
2135
Ed Tanous23a21a12020-07-25 04:45:05 +00002136inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002137{
2138 if (rfAction == "None")
2139 {
2140 return "xyz.openbmc_project.State.Watchdog.Action.None";
2141 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002142 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002143 {
2144 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2145 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002146 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002147 {
2148 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2149 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002150 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002151 {
2152 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2153 }
2154
2155 return "";
2156}
2157
2158/**
Yong Li51709ff2019-09-30 14:13:04 +08002159 * @brief Retrieves host watchdog timer properties over DBUS
2160 *
2161 * @param[in] aResp Shared pointer for completing asynchronous calls.
2162 *
2163 * @return None.
2164 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002165inline void
2166 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002167{
2168 BMCWEB_LOG_DEBUG << "Get host watchodg";
2169 crow::connections::systemBus->async_method_call(
2170 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002171 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002172 if (ec)
2173 {
2174 // watchdog service is stopped
2175 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2176 return;
2177 }
2178
2179 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2180
2181 nlohmann::json& hostWatchdogTimer =
2182 aResp->res.jsonValue["HostWatchdogTimer"];
2183
2184 // watchdog service is running/enabled
2185 hostWatchdogTimer["Status"]["State"] = "Enabled";
2186
2187 for (const auto& property : properties)
2188 {
2189 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2190 if (property.first == "Enabled")
Yong Li51709ff2019-09-30 14:13:04 +08002191 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002192 const bool* state = std::get_if<bool>(&property.second);
2193
2194 if (state == nullptr)
2195 {
2196 messages::internalError(aResp->res);
2197 return;
2198 }
2199
2200 hostWatchdogTimer["FunctionEnabled"] = *state;
Yong Li51709ff2019-09-30 14:13:04 +08002201 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002202 else if (property.first == "ExpireAction")
Yong Li51709ff2019-09-30 14:13:04 +08002203 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002204 const std::string* s =
2205 std::get_if<std::string>(&property.second);
2206 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002207 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002208 messages::internalError(aResp->res);
2209 return;
Yong Li51709ff2019-09-30 14:13:04 +08002210 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002211
2212 std::string action = dbusToRfWatchdogAction(*s);
2213 if (action.empty())
Yong Li51709ff2019-09-30 14:13:04 +08002214 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002215 messages::internalError(aResp->res);
2216 return;
Yong Li51709ff2019-09-30 14:13:04 +08002217 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002218 hostWatchdogTimer["TimeoutAction"] = action;
Yong Li51709ff2019-09-30 14:13:04 +08002219 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002220 }
Yong Li51709ff2019-09-30 14:13:04 +08002221 },
2222 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2223 "org.freedesktop.DBus.Properties", "GetAll",
2224 "xyz.openbmc_project.State.Watchdog");
2225}
2226
2227/**
Yong Lic45f0082019-10-10 14:19:01 +08002228 * @brief Sets Host WatchDog Timer properties.
2229 *
2230 * @param[in] aResp Shared pointer for generating response message.
2231 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2232 * RF request.
2233 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2234 *
2235 * @return None.
2236 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002237inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002238 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002239 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002240{
2241 BMCWEB_LOG_DEBUG << "Set host watchdog";
2242
2243 if (wdtTimeOutAction)
2244 {
2245 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2246 // check if TimeOut Action is Valid
2247 if (wdtTimeOutActStr.empty())
2248 {
2249 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2250 << *wdtTimeOutAction;
2251 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2252 "TimeoutAction");
2253 return;
2254 }
2255
2256 crow::connections::systemBus->async_method_call(
2257 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002258 if (ec)
2259 {
2260 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2261 messages::internalError(aResp->res);
2262 return;
2263 }
Yong Lic45f0082019-10-10 14:19:01 +08002264 },
2265 "xyz.openbmc_project.Watchdog",
2266 "/xyz/openbmc_project/watchdog/host0",
2267 "org.freedesktop.DBus.Properties", "Set",
2268 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002269 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002270 }
2271
2272 if (wdtEnable)
2273 {
2274 crow::connections::systemBus->async_method_call(
2275 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002276 if (ec)
2277 {
2278 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2279 messages::internalError(aResp->res);
2280 return;
2281 }
Yong Lic45f0082019-10-10 14:19:01 +08002282 },
2283 "xyz.openbmc_project.Watchdog",
2284 "/xyz/openbmc_project/watchdog/host0",
2285 "org.freedesktop.DBus.Properties", "Set",
2286 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002287 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002288 }
2289}
2290
Chris Cain37bbf982021-09-20 10:53:09 -05002291using ipsPropertiesType =
2292 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2293/**
2294 * @brief Parse the Idle Power Saver properties into json
2295 *
2296 * @param[in] aResp Shared pointer for completing asynchronous calls.
2297 * @param[in] properties IPS property data from DBus.
2298 *
2299 * @return true if successful
2300 */
Ed Tanousf6674222021-11-13 09:41:41 -08002301inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanous02cad962022-06-30 16:50:15 -07002302 const ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002303{
2304 for (const auto& property : properties)
2305 {
2306 if (property.first == "Enabled")
2307 {
2308 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002309 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002310 {
2311 return false;
2312 }
2313 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2314 }
2315 else if (property.first == "EnterUtilizationPercent")
2316 {
2317 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002318 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002319 {
2320 return false;
2321 }
2322 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2323 }
2324 else if (property.first == "EnterDwellTime")
2325 {
2326 // Convert Dbus time from milliseconds to seconds
2327 const uint64_t* timeMilliseconds =
2328 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002329 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002330 {
2331 return false;
2332 }
2333 const std::chrono::duration<uint64_t, std::milli> ms(
2334 *timeMilliseconds);
2335 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2336 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2337 .count();
2338 }
2339 else if (property.first == "ExitUtilizationPercent")
2340 {
2341 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002342 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002343 {
2344 return false;
2345 }
2346 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2347 }
2348 else if (property.first == "ExitDwellTime")
2349 {
2350 // Convert Dbus time from milliseconds to seconds
2351 const uint64_t* timeMilliseconds =
2352 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002353 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002354 {
2355 return false;
2356 }
2357 const std::chrono::duration<uint64_t, std::milli> ms(
2358 *timeMilliseconds);
2359 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2360 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2361 .count();
2362 }
2363 else
2364 {
2365 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2366 << property.first;
2367 }
2368 }
2369
2370 return true;
2371}
2372
2373/**
2374 * @brief Retrieves host watchdog timer properties over DBUS
2375 *
2376 * @param[in] aResp Shared pointer for completing asynchronous calls.
2377 *
2378 * @return None.
2379 */
2380inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2381{
2382 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2383
2384 // Get IdlePowerSaver object path:
2385 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002386 [aResp](const boost::system::error_code ec,
2387 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002388 if (ec)
2389 {
2390 BMCWEB_LOG_DEBUG
2391 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2392 << ec;
2393 messages::internalError(aResp->res);
2394 return;
2395 }
2396 if (subtree.empty())
2397 {
2398 // This is an optional interface so just return
2399 // if there is no instance found
2400 BMCWEB_LOG_DEBUG << "No instances found";
2401 return;
2402 }
2403 if (subtree.size() > 1)
2404 {
2405 // More then one PowerIdlePowerSaver object is not supported and
2406 // is an error
2407 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2408 "Power.IdlePowerSaver objects: "
2409 << subtree.size();
2410 messages::internalError(aResp->res);
2411 return;
2412 }
2413 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2414 {
2415 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2416 messages::internalError(aResp->res);
2417 return;
2418 }
2419 const std::string& path = subtree[0].first;
2420 const std::string& service = subtree[0].second.begin()->first;
2421 if (service.empty())
2422 {
2423 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2424 messages::internalError(aResp->res);
2425 return;
2426 }
2427
2428 // Valid IdlePowerSaver object found, now read the current values
2429 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002430 [aResp](const boost::system::error_code ec2,
Ed Tanous02cad962022-06-30 16:50:15 -07002431 const ipsPropertiesType& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002432 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002433 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002434 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002435 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002436 messages::internalError(aResp->res);
2437 return;
2438 }
2439
Ed Tanous002d39b2022-05-31 08:59:27 -07002440 if (!parseIpsProperties(aResp, properties))
2441 {
2442 messages::internalError(aResp->res);
2443 return;
2444 }
2445 },
2446 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2447 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
Chris Cain37bbf982021-09-20 10:53:09 -05002448 },
2449 "xyz.openbmc_project.ObjectMapper",
2450 "/xyz/openbmc_project/object_mapper",
2451 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2452 std::array<const char*, 1>{
2453 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2454
2455 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2456}
2457
2458/**
2459 * @brief Sets Idle Power Saver properties.
2460 *
2461 * @param[in] aResp Shared pointer for generating response message.
2462 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2463 * RF request.
2464 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2465 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2466 * before entering idle state.
2467 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2468 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2469 * before exiting idle state
2470 *
2471 * @return None.
2472 */
2473inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2474 const std::optional<bool> ipsEnable,
2475 const std::optional<uint8_t> ipsEnterUtil,
2476 const std::optional<uint64_t> ipsEnterTime,
2477 const std::optional<uint8_t> ipsExitUtil,
2478 const std::optional<uint64_t> ipsExitTime)
2479{
2480 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2481
2482 // Get IdlePowerSaver object path:
2483 crow::connections::systemBus->async_method_call(
2484 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002485 ipsExitTime](const boost::system::error_code ec,
2486 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002487 if (ec)
2488 {
2489 BMCWEB_LOG_DEBUG
2490 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2491 << ec;
2492 messages::internalError(aResp->res);
2493 return;
2494 }
2495 if (subtree.empty())
2496 {
2497 // This is an optional D-Bus object, but user attempted to patch
2498 messages::resourceNotFound(aResp->res, "ComputerSystem",
2499 "IdlePowerSaver");
2500 return;
2501 }
2502 if (subtree.size() > 1)
2503 {
2504 // More then one PowerIdlePowerSaver object is not supported and
2505 // is an error
2506 BMCWEB_LOG_DEBUG
2507 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2508 << subtree.size();
2509 messages::internalError(aResp->res);
2510 return;
2511 }
2512 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2513 {
2514 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2515 messages::internalError(aResp->res);
2516 return;
2517 }
2518 const std::string& path = subtree[0].first;
2519 const std::string& service = subtree[0].second.begin()->first;
2520 if (service.empty())
2521 {
2522 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2523 messages::internalError(aResp->res);
2524 return;
2525 }
Chris Cain37bbf982021-09-20 10:53:09 -05002526
Ed Tanous002d39b2022-05-31 08:59:27 -07002527 // Valid Power IdlePowerSaver object found, now set any values that
2528 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002529
Ed Tanous002d39b2022-05-31 08:59:27 -07002530 if (ipsEnable)
2531 {
2532 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002533 [aResp](const boost::system::error_code ec2) {
2534 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002535 {
Ed Tanous8a592812022-06-04 09:06:59 -07002536 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002537 messages::internalError(aResp->res);
2538 return;
2539 }
2540 },
2541 service, path, "org.freedesktop.DBus.Properties", "Set",
2542 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2543 dbus::utility::DbusVariantType(*ipsEnable));
2544 }
2545 if (ipsEnterUtil)
2546 {
2547 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002548 [aResp](const boost::system::error_code ec2) {
2549 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002550 {
Ed Tanous8a592812022-06-04 09:06:59 -07002551 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002552 messages::internalError(aResp->res);
2553 return;
2554 }
2555 },
2556 service, path, "org.freedesktop.DBus.Properties", "Set",
2557 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2558 "EnterUtilizationPercent",
2559 dbus::utility::DbusVariantType(*ipsEnterUtil));
2560 }
2561 if (ipsEnterTime)
2562 {
2563 // Convert from seconds into milliseconds for DBus
2564 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2565 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002566 [aResp](const boost::system::error_code ec2) {
2567 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002568 {
Ed Tanous8a592812022-06-04 09:06:59 -07002569 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002570 messages::internalError(aResp->res);
2571 return;
2572 }
2573 },
2574 service, path, "org.freedesktop.DBus.Properties", "Set",
2575 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2576 "EnterDwellTime",
2577 dbus::utility::DbusVariantType(timeMilliseconds));
2578 }
2579 if (ipsExitUtil)
2580 {
2581 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002582 [aResp](const boost::system::error_code ec2) {
2583 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002584 {
Ed Tanous8a592812022-06-04 09:06:59 -07002585 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002586 messages::internalError(aResp->res);
2587 return;
2588 }
2589 },
2590 service, path, "org.freedesktop.DBus.Properties", "Set",
2591 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2592 "ExitUtilizationPercent",
2593 dbus::utility::DbusVariantType(*ipsExitUtil));
2594 }
2595 if (ipsExitTime)
2596 {
2597 // Convert from seconds into milliseconds for DBus
2598 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2599 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002600 [aResp](const boost::system::error_code ec2) {
2601 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002602 {
Ed Tanous8a592812022-06-04 09:06:59 -07002603 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002604 messages::internalError(aResp->res);
2605 return;
2606 }
2607 },
2608 service, path, "org.freedesktop.DBus.Properties", "Set",
2609 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2610 "ExitDwellTime",
2611 dbus::utility::DbusVariantType(timeMilliseconds));
2612 }
Chris Cain37bbf982021-09-20 10:53:09 -05002613 },
2614 "xyz.openbmc_project.ObjectMapper",
2615 "/xyz/openbmc_project/object_mapper",
2616 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2617 std::array<const char*, 1>{
2618 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2619
2620 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2621}
2622
Yong Lic45f0082019-10-10 14:19:01 +08002623/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002624 * SystemsCollection derived class for delivering ComputerSystems Collection
2625 * Schema
2626 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002627inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002628{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002629 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002630 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002631 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002632 [&app](const crow::Request& req,
2633 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002634 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002635 {
2636 return;
2637 }
2638 asyncResp->res.jsonValue["@odata.type"] =
2639 "#ComputerSystemCollection.ComputerSystemCollection";
2640 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2641 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002642
Ed Tanous002d39b2022-05-31 08:59:27 -07002643 sdbusplus::asio::getProperty<std::string>(
2644 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2645 "/xyz/openbmc_project/network/hypervisor",
2646 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous8a592812022-06-04 09:06:59 -07002647 [asyncResp](const boost::system::error_code ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002648 const std::string& /*hostName*/) {
2649 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2650 ifaceArray = nlohmann::json::array();
2651 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002652
Ed Tanous002d39b2022-05-31 08:59:27 -07002653 nlohmann::json::object_t system;
2654 system["@odata.id"] = "/redfish/v1/Systems/system";
2655 ifaceArray.push_back(std::move(system));
2656 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002657 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002658 {
2659 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2660 nlohmann::json::object_t hypervisor;
2661 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2662 ifaceArray.push_back(std::move(hypervisor));
2663 count = ifaceArray.size();
2664 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002665 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002666 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002667}
Sunitha Harish462023a2020-02-19 08:34:59 -06002668
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002669/**
2670 * Function transceives data with dbus directly.
2671 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002672inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002673{
2674 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2675 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2676 constexpr char const* interfaceName =
2677 "xyz.openbmc_project.Control.Host.NMI";
2678 constexpr char const* method = "NMI";
2679
2680 crow::connections::systemBus->async_method_call(
2681 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002682 if (ec)
2683 {
2684 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2685 messages::internalError(asyncResp->res);
2686 return;
2687 }
2688 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002689 },
2690 serviceName, objectPath, interfaceName, method);
2691}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002692
2693/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002694 * SystemActionsReset class supports handle POST method for Reset action.
2695 * The class retrieves and sends data directly to D-Bus.
2696 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002697inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002698{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002699 /**
2700 * Function handles POST method request.
2701 * Analyzes POST body message before sends Reset request data to D-Bus.
2702 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002703 BMCWEB_ROUTE(app,
2704 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002705 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002706 .methods(boost::beast::http::verb::post)(
2707 [&app](const crow::Request& req,
2708 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002709 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002710 {
2711 return;
2712 }
2713 std::string resetType;
2714 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2715 resetType))
2716 {
2717 return;
2718 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002719
Ed Tanous002d39b2022-05-31 08:59:27 -07002720 // Get the command and host vs. chassis
2721 std::string command;
2722 bool hostCommand = true;
2723 if ((resetType == "On") || (resetType == "ForceOn"))
2724 {
2725 command = "xyz.openbmc_project.State.Host.Transition.On";
2726 hostCommand = true;
2727 }
2728 else if (resetType == "ForceOff")
2729 {
2730 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2731 hostCommand = false;
2732 }
2733 else if (resetType == "ForceRestart")
2734 {
2735 command =
2736 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2737 hostCommand = true;
2738 }
2739 else if (resetType == "GracefulShutdown")
2740 {
2741 command = "xyz.openbmc_project.State.Host.Transition.Off";
2742 hostCommand = true;
2743 }
2744 else if (resetType == "GracefulRestart")
2745 {
2746 command =
2747 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2748 hostCommand = true;
2749 }
2750 else if (resetType == "PowerCycle")
2751 {
2752 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2753 hostCommand = true;
2754 }
2755 else if (resetType == "Nmi")
2756 {
2757 doNMI(asyncResp);
2758 return;
2759 }
2760 else
2761 {
2762 messages::actionParameterUnknown(asyncResp->res, "Reset",
2763 resetType);
2764 return;
2765 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002766
Ed Tanous002d39b2022-05-31 08:59:27 -07002767 if (hostCommand)
2768 {
2769 crow::connections::systemBus->async_method_call(
2770 [asyncResp, resetType](const boost::system::error_code ec) {
2771 if (ec)
2772 {
2773 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2774 if (ec.value() == boost::asio::error::invalid_argument)
2775 {
2776 messages::actionParameterNotSupported(
2777 asyncResp->res, resetType, "Reset");
2778 }
2779 else
2780 {
2781 messages::internalError(asyncResp->res);
2782 }
2783 return;
2784 }
2785 messages::success(asyncResp->res);
2786 },
2787 "xyz.openbmc_project.State.Host",
2788 "/xyz/openbmc_project/state/host0",
2789 "org.freedesktop.DBus.Properties", "Set",
2790 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2791 dbus::utility::DbusVariantType{command});
2792 }
2793 else
2794 {
2795 crow::connections::systemBus->async_method_call(
2796 [asyncResp, resetType](const boost::system::error_code ec) {
2797 if (ec)
2798 {
2799 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2800 if (ec.value() == boost::asio::error::invalid_argument)
2801 {
2802 messages::actionParameterNotSupported(
2803 asyncResp->res, resetType, "Reset");
2804 }
2805 else
2806 {
2807 messages::internalError(asyncResp->res);
2808 }
2809 return;
2810 }
2811 messages::success(asyncResp->res);
2812 },
2813 "xyz.openbmc_project.State.Chassis",
2814 "/xyz/openbmc_project/state/chassis0",
2815 "org.freedesktop.DBus.Properties", "Set",
2816 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2817 dbus::utility::DbusVariantType{command});
2818 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 });
2820}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002821
2822/**
Ed Tanous66173382018-08-15 18:20:59 -07002823 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002824 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002825inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002826{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002827
Ed Tanous1abe55e2018-09-05 08:30:59 -07002828 /**
2829 * Functions triggers appropriate requests on DBus
2830 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002832 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002833 .methods(boost::beast::http::verb::get)(
2834 [&app](const crow::Request& req,
2835 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002836 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002837 {
2838 return;
2839 }
2840 asyncResp->res.jsonValue["@odata.type"] =
2841 "#ComputerSystem.v1_16_0.ComputerSystem";
2842 asyncResp->res.jsonValue["Name"] = "system";
2843 asyncResp->res.jsonValue["Id"] = "system";
2844 asyncResp->res.jsonValue["SystemType"] = "Physical";
2845 asyncResp->res.jsonValue["Description"] = "Computer System";
2846 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2847 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2848 "Disabled";
2849 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2850 uint64_t(0);
2851 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2852 "Disabled";
2853 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002854
Ed Tanous002d39b2022-05-31 08:59:27 -07002855 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
2856 "/redfish/v1/Systems/system/Processors";
2857 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
2858 "/redfish/v1/Systems/system/Memory";
2859 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
2860 "/redfish/v1/Systems/system/Storage";
Ed Tanous029573d2019-02-01 10:57:49 -08002861
Ed Tanous002d39b2022-05-31 08:59:27 -07002862 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
2863 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
2864 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
2865 ["@Redfish.ActionInfo"] =
2866 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002867
Ed Tanous002d39b2022-05-31 08:59:27 -07002868 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
2869 "/redfish/v1/Systems/system/LogServices";
2870 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
2871 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002872
Ed Tanous002d39b2022-05-31 08:59:27 -07002873 nlohmann::json::array_t managedBy;
2874 nlohmann::json& manager = managedBy.emplace_back();
2875 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
2876 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
2877 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
2878 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002879
Ed Tanous002d39b2022-05-31 08:59:27 -07002880 // Fill in SerialConsole info
2881 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
2882 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
2883 true;
Ed Tanous14766872022-03-15 10:44:42 -07002884
Ed Tanous002d39b2022-05-31 08:59:27 -07002885 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2886 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
2887 true;
2888 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
2889 asyncResp->res
2890 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
2891 "Press ~. to exit console";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002892
2893#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002894 // Fill in GraphicalConsole info
2895 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
2896 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
2897 4;
2898 asyncResp->res
2899 .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"};
Ed Tanous14766872022-03-15 10:44:42 -07002900
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002901#endif // BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002902 constexpr const std::array<const char*, 4> inventoryForSystems = {
2903 "xyz.openbmc_project.Inventory.Item.Dimm",
2904 "xyz.openbmc_project.Inventory.Item.Cpu",
2905 "xyz.openbmc_project.Inventory.Item.Drive",
2906 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002907
Ed Tanous002d39b2022-05-31 08:59:27 -07002908 auto health = std::make_shared<HealthPopulate>(asyncResp);
2909 crow::connections::systemBus->async_method_call(
2910 [health](const boost::system::error_code ec,
2911 const std::vector<std::string>& resp) {
2912 if (ec)
2913 {
2914 // no inventory
2915 return;
2916 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002917
Ed Tanous002d39b2022-05-31 08:59:27 -07002918 health->inventory = resp;
2919 },
2920 "xyz.openbmc_project.ObjectMapper",
2921 "/xyz/openbmc_project/object_mapper",
2922 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2923 int32_t(0), inventoryForSystems);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002924
Ed Tanous002d39b2022-05-31 08:59:27 -07002925 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002926
Ed Tanous002d39b2022-05-31 08:59:27 -07002927 getMainChassisId(asyncResp,
2928 [](const std::string& chassisId,
2929 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2930 nlohmann::json::array_t chassisArray;
2931 nlohmann::json& chassis = chassisArray.emplace_back();
2932 chassis["@odata.id"] = "/redfish/v1/Chassis/" + chassisId;
2933 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
2934 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002935
Ed Tanous002d39b2022-05-31 08:59:27 -07002936 getLocationIndicatorActive(asyncResp);
2937 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2938 getIndicatorLedState(asyncResp);
2939 getComputerSystem(asyncResp, health);
2940 getHostState(asyncResp);
2941 getBootProperties(asyncResp);
2942 getBootProgress(asyncResp);
2943 getPCIeDeviceList(asyncResp, "PCIeDevices");
2944 getHostWatchdogTimer(asyncResp);
2945 getPowerRestorePolicy(asyncResp);
2946 getAutomaticRetry(asyncResp);
2947 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002948#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07002949 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002950#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07002951 getTrustedModuleRequiredToBoot(asyncResp);
2952 getPowerMode(asyncResp);
2953 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002954 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002955
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002956 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002957 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002958 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002959 [&app](const crow::Request& req,
2960 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002961 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002962 {
2963 return;
2964 }
2965 std::optional<bool> locationIndicatorActive;
2966 std::optional<std::string> indicatorLed;
2967 std::optional<std::string> assetTag;
2968 std::optional<std::string> powerRestorePolicy;
2969 std::optional<std::string> powerMode;
2970 std::optional<bool> wdtEnable;
2971 std::optional<std::string> wdtTimeOutAction;
2972 std::optional<std::string> bootSource;
2973 std::optional<std::string> bootType;
2974 std::optional<std::string> bootEnable;
2975 std::optional<std::string> bootAutomaticRetry;
2976 std::optional<bool> bootTrustedModuleRequired;
2977 std::optional<bool> ipsEnable;
2978 std::optional<uint8_t> ipsEnterUtil;
2979 std::optional<uint64_t> ipsEnterTime;
2980 std::optional<uint8_t> ipsExitUtil;
2981 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002982
Ed Tanous002d39b2022-05-31 08:59:27 -07002983 // clang-format off
Jiaqing Zhaoaa6d4532022-06-02 17:47:58 +08002984 if (!json_util::readJsonPatch(
2985 req, asyncResp->res,
2986 "IndicatorLED", indicatorLed,
2987 "LocationIndicatorActive", locationIndicatorActive,
2988 "AssetTag", assetTag,
2989 "PowerRestorePolicy", powerRestorePolicy,
2990 "PowerMode", powerMode,
2991 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
2992 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
2993 "Boot/BootSourceOverrideTarget", bootSource,
2994 "Boot/BootSourceOverrideMode", bootType,
2995 "Boot/BootSourceOverrideEnabled", bootEnable,
2996 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
2997 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
2998 "IdlePowerSaver/Enabled", ipsEnable,
2999 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3000 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3001 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3002 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3003 {
3004 return;
3005 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003006 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003007
Ed Tanous002d39b2022-05-31 08:59:27 -07003008 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003009
Ed Tanous002d39b2022-05-31 08:59:27 -07003010 if (assetTag)
3011 {
3012 setAssetTag(asyncResp, *assetTag);
3013 }
James Feistb49ac872019-05-21 15:12:01 -07003014
Ed Tanous002d39b2022-05-31 08:59:27 -07003015 if (wdtEnable || wdtTimeOutAction)
3016 {
3017 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3018 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003019
Ed Tanous002d39b2022-05-31 08:59:27 -07003020 if (bootSource || bootType || bootEnable)
3021 {
3022 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3023 }
3024 if (bootAutomaticRetry)
3025 {
3026 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3027 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003028
Ed Tanous002d39b2022-05-31 08:59:27 -07003029 if (bootTrustedModuleRequired)
3030 {
3031 setTrustedModuleRequiredToBoot(asyncResp,
3032 *bootTrustedModuleRequired);
3033 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003034
Ed Tanous002d39b2022-05-31 08:59:27 -07003035 if (locationIndicatorActive)
3036 {
3037 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3038 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039
Ed Tanous002d39b2022-05-31 08:59:27 -07003040 // TODO (Gunnar): Remove IndicatorLED after enough time has
3041 // passed
3042 if (indicatorLed)
3043 {
3044 setIndicatorLedState(asyncResp, *indicatorLed);
3045 asyncResp->res.addHeader(boost::beast::http::field::warning,
3046 "299 - \"IndicatorLED is deprecated. Use "
3047 "LocationIndicatorActive instead.\"");
3048 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003049
Ed Tanous002d39b2022-05-31 08:59:27 -07003050 if (powerRestorePolicy)
3051 {
3052 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3053 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003054
Ed Tanous002d39b2022-05-31 08:59:27 -07003055 if (powerMode)
3056 {
3057 setPowerMode(asyncResp, *powerMode);
3058 }
Chris Cain37bbf982021-09-20 10:53:09 -05003059
Ed Tanous002d39b2022-05-31 08:59:27 -07003060 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3061 ipsExitTime)
3062 {
3063 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3064 ipsExitUtil, ipsExitTime);
3065 }
3066 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003067}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303068
3069/**
3070 * SystemResetActionInfo derived class for delivering Computer Systems
3071 * ResetType AllowableValues using ResetInfo schema.
3072 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003073inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303074{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303075 /**
3076 * Functions triggers appropriate requests on DBus
3077 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003078 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003079 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003080 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003081 [&app](const crow::Request& req,
3082 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003083 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003084 {
3085 return;
3086 }
Ed Tanous14766872022-03-15 10:44:42 -07003087
Ed Tanous002d39b2022-05-31 08:59:27 -07003088 asyncResp->res.jsonValue["@odata.id"] =
3089 "/redfish/v1/Systems/system/ResetActionInfo";
3090 asyncResp->res.jsonValue["@odata.type"] =
3091 "#ActionInfo.v1_1_2.ActionInfo";
3092 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3093 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003094
3095 nlohmann::json::array_t parameters;
3096 nlohmann::json::object_t parameter;
3097
3098 parameter["Name"] = "ResetType";
3099 parameter["Required"] = true;
3100 parameter["DataType"] = "String";
3101 nlohmann::json::array_t allowableValues;
3102 allowableValues.emplace_back("On");
3103 allowableValues.emplace_back("ForceOff");
3104 allowableValues.emplace_back("ForceOn");
3105 allowableValues.emplace_back("ForceRestart");
3106 allowableValues.emplace_back("GracefulRestart");
3107 allowableValues.emplace_back("GracefulShutdown");
3108 allowableValues.emplace_back("PowerCycle");
3109 allowableValues.emplace_back("Nmi");
3110 parameter["AllowableValues"] = std::move(allowableValues);
3111 parameters.emplace_back(std::move(parameter));
3112
3113 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003114 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003115}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003116} // namespace redfish