blob: 230598b809d51e088a5d712092b929c820ca3627 [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"
Ed Tanous2b829372022-08-03 14:22:34 -070024#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080025
John Edward Broadbent7e860f12021-04-08 15:57:16 -070026#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070027#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080028#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070029#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070030#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020031#include <sdbusplus/unpack_properties.hpp>
32#include <utils/dbus_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033#include <utils/json_utils.hpp>
Willy Tueee00132022-06-14 14:53:17 -070034#include <utils/sw_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050035
Ed Tanousabf2add2019-01-22 16:40:12 -080036#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020037
Ed Tanous1abe55e2018-09-05 08:30:59 -070038namespace redfish
39{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020040
Alpana Kumari9d3ae102019-04-12 06:49:32 -050041/**
42 * @brief Updates the Functional State of DIMMs
43 *
44 * @param[in] aResp Shared pointer for completing asynchronous calls
45 * @param[in] dimmState Dimm's Functional state, true/false
46 *
47 * @return None.
48 */
zhanghch058d1b46d2021-04-01 11:18:24 +080049inline void
50 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070051 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070053 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050054
Gunnar Mills4e0453b2020-07-08 14:00:30 -050055 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050056 // Update STATE only if previous State was DISABLED and current Dimm is
57 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070058 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
60 if (prevMemSummary == "Disabled")
61 {
Ed Tanouse05aec52022-01-25 10:28:56 -080062 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050063 {
64 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
65 "Enabled";
66 }
67 }
68}
69
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050070/*
71 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
72 *
73 * @param[in] aResp Shared pointer for completing asynchronous calls
74 * @param[in] cpuPresenceState CPU present or not
75 *
76 * @return None.
77 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070078inline void
79 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
80 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070082 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050083
Ed Tanous55f79e62022-01-25 11:26:16 -080084 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050085 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050086 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080087 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080088 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050089 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080090 if (procCountPtr != nullptr)
91 {
92 // shouldn't be possible to be nullptr
93 *procCountPtr += 1;
94 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050095 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050096}
97
98/*
99 * @brief Update "ProcessorSummary" "Status" "State" based on
100 * CPU Functional State
101 *
102 * @param[in] aResp Shared pointer for completing asynchronous calls
103 * @param[in] cpuFunctionalState is CPU functional true/false
104 *
105 * @return None.
106 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700107inline void
108 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
109 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700111 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500112
Ed Tanous02cad962022-06-30 16:50:15 -0700113 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
115
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500116 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500117 // Update STATE only if previous State was Non_Functional and current CPU is
118 // Functional.
119 if (prevProcState == "Disabled")
120 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800121 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500122 {
123 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
124 "Enabled";
125 }
126 }
127}
128
Ed Tanousb9d36b42022-02-26 21:42:46 -0800129inline void
130 getProcessorProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
131 const std::string& service, const std::string& path,
132 const dbus::utility::DBusPropertiesMap& properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500133{
134
135 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
136
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700137 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
138 const bool cpuPresenceCheck) {
139 if (ec3)
140 {
141 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
142 return;
143 }
144 modifyCpuPresenceState(aResp, cpuPresenceCheck);
145 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500146
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700147 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
148 const bool cpuFunctionalCheck) {
149 if (ec3)
150 {
151 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
152 return;
153 }
154 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
155 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500156
157 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700158 sdbusplus::asio::getProperty<bool>(
159 *crow::connections::systemBus, service, path,
160 "xyz.openbmc_project.Inventory.Item", "Present",
161 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500162
163 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700164 sdbusplus::asio::getProperty<bool>(
165 *crow::connections::systemBus, service, path,
166 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
167 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500168
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200169 // TODO: Get Model
170
171 const uint16_t* coreCount = nullptr;
172
173 const bool success = sdbusplus::unpackPropertiesNoThrow(
174 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
175
176 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500177 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200178 messages::internalError(aResp->res);
179 return;
180 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500181
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200182 if (coreCount != nullptr)
183 {
184 nlohmann::json& coreCountJson =
185 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
186 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500187
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200188 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500189 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200190 coreCountJson = *coreCount;
191 }
192 else
193 {
194 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500195 }
196 }
197}
198
199/*
200 * @brief Get ProcessorSummary fields
201 *
202 * @param[in] aResp Shared pointer for completing asynchronous calls
203 * @param[in] service dbus service for Cpu Information
204 * @param[in] path dbus path for Cpu
205 *
206 * @return None.
207 */
208inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
209 const std::string& service,
210 const std::string& path)
211{
212
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200213 sdbusplus::asio::getAllProperties(
214 *crow::connections::systemBus, service, path,
215 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500216 [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);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200226 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500227}
228
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500229/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700230 * @brief Retrieves computer system properties over dbus
231 *
232 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500233 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700234 *
235 * @return None.
236 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700237inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800238 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700239 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700240{
Ed Tanous6c34de42018-08-29 13:37:36 -0700241 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500242
Ed Tanous6c34de42018-08-29 13:37:36 -0700243 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800244 [aResp,
245 systemHealth](const boost::system::error_code ec,
246 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700247 if (ec)
248 {
249 BMCWEB_LOG_DEBUG << "DBUS response error";
250 messages::internalError(aResp->res);
251 return;
252 }
253 // Iterate over all retrieved ObjectPaths.
254 for (const std::pair<
255 std::string,
256 std::vector<std::pair<std::string, std::vector<std::string>>>>&
257 object : subtree)
258 {
259 const std::string& path = object.first;
260 BMCWEB_LOG_DEBUG << "Got path: " << path;
261 const std::vector<std::pair<std::string, std::vector<std::string>>>&
262 connectionNames = object.second;
263 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700264 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700265 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700267
268 auto memoryHealth = std::make_shared<HealthPopulate>(
269 aResp, "/MemorySummary/Status"_json_pointer);
270
271 auto cpuHealth = std::make_shared<HealthPopulate>(
272 aResp, "/ProcessorSummary/Status"_json_pointer);
273
274 systemHealth->children.emplace_back(memoryHealth);
275 systemHealth->children.emplace_back(cpuHealth);
276
277 // This is not system, so check if it's cpu, dimm, UUID or
278 // BiosVer
279 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700280 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700281 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700282 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700283 if (interfaceName ==
284 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700285 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700286 BMCWEB_LOG_DEBUG
287 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500288
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200289 sdbusplus::asio::getAllProperties(
290 *crow::connections::systemBus, connection.first,
291 path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanous002d39b2022-05-31 08:59:27 -0700292 [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
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200306 if (properties.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700307 {
308 sdbusplus::asio::getProperty<bool>(
309 *crow::connections::systemBus, service,
310 path,
311 "xyz.openbmc_project.State."
312 "Decorator.OperationalStatus",
313 "Functional",
314 [aResp](const boost::system::error_code ec3,
315 bool dimmState) {
316 if (ec3)
317 {
318 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000319 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800320 return;
321 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700322 updateDimmProperties(aResp, dimmState);
323 });
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200324 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700325 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200326
327 const uint32_t* memorySizeInKB = nullptr;
328
329 const bool success =
330 sdbusplus::unpackPropertiesNoThrow(
331 dbus_utils::UnpackErrorPrinter(),
332 properties, "MemorySizeInKB",
333 memorySizeInKB);
334
335 if (!success)
336 {
337 messages::internalError(aResp->res);
338 return;
339 }
340
341 if (memorySizeInKB != nullptr)
342 {
343 nlohmann::json& totalMemory =
344 aResp->res
345 .jsonValue["MemorySummary"]
346 ["TotalSystemMemoryGiB"];
347 const uint64_t* preValue =
348 totalMemory.get_ptr<const uint64_t*>();
349 if (preValue == nullptr)
350 {
351 aResp->res
352 .jsonValue["MemorySummary"]
353 ["TotalSystemMemoryGiB"] =
354 *memorySizeInKB / (1024 * 1024);
355 }
356 else
357 {
358 aResp->res
359 .jsonValue["MemorySummary"]
360 ["TotalSystemMemoryGiB"] =
361 *memorySizeInKB / (1024 * 1024) +
362 *preValue;
363 }
364 aResp->res.jsonValue["MemorySummary"]["Status"]
365 ["State"] = "Enabled";
366 }
367 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700368
369 memoryHealth->inventory.emplace_back(path);
370 }
371 else if (interfaceName ==
372 "xyz.openbmc_project.Inventory.Item.Cpu")
373 {
374 BMCWEB_LOG_DEBUG
375 << "Found Cpu, now get its properties.";
376
377 getProcessorSummary(aResp, connection.first, path);
378
379 cpuHealth->inventory.emplace_back(path);
380 }
381 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
382 {
383 BMCWEB_LOG_DEBUG
384 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200385
386 sdbusplus::asio::getAllProperties(
387 *crow::connections::systemBus, connection.first,
388 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous002d39b2022-05-31 08:59:27 -0700389 [aResp](const boost::system::error_code ec3,
390 const dbus::utility::DBusPropertiesMap&
391 properties) {
392 if (ec3)
393 {
394 BMCWEB_LOG_DEBUG << "DBUS response error "
395 << ec3;
396 messages::internalError(aResp->res);
397 return;
398 }
399 BMCWEB_LOG_DEBUG << "Got " << properties.size()
400 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700401
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200402 const std::string* uUID = nullptr;
403
404 const bool success =
405 sdbusplus::unpackPropertiesNoThrow(
406 dbus_utils::UnpackErrorPrinter(),
407 properties, "UUID", uUID);
408
409 if (!success)
410 {
411 messages::internalError(aResp->res);
412 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700413 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200414
415 if (uUID != nullptr)
416 {
417 std::string valueStr = *uUID;
418 if (valueStr.size() == 32)
419 {
420 valueStr.insert(8, 1, '-');
421 valueStr.insert(13, 1, '-');
422 valueStr.insert(18, 1, '-');
423 valueStr.insert(23, 1, '-');
424 }
425 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
426 aResp->res.jsonValue["UUID"] = valueStr;
427 }
428 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700429 }
430 else if (interfaceName ==
431 "xyz.openbmc_project.Inventory.Item.System")
432 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200433 sdbusplus::asio::getAllProperties(
434 *crow::connections::systemBus, connection.first,
435 path,
436 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous002d39b2022-05-31 08:59:27 -0700437 [aResp](const boost::system::error_code ec2,
438 const dbus::utility::DBusPropertiesMap&
439 propertiesList) {
440 if (ec2)
441 {
442 // doesn't have to include this
443 // interface
444 return;
445 }
446 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
447 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200448
449 const std::string* partNumber = nullptr;
450 const std::string* serialNumber = nullptr;
451 const std::string* manufacturer = nullptr;
452 const std::string* model = nullptr;
453 const std::string* subModel = nullptr;
454
455 const bool success =
456 sdbusplus::unpackPropertiesNoThrow(
457 dbus_utils::UnpackErrorPrinter(),
458 propertiesList, "PartNumber", partNumber,
459 "SerialNumber", serialNumber,
460 "Manufacturer", manufacturer, "Model",
461 model, "SubModel", subModel);
462
463 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700464 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200465 messages::internalError(aResp->res);
466 return;
467 }
468
469 if (partNumber != nullptr)
470 {
471 aResp->res.jsonValue["PartNumber"] =
472 *partNumber;
473 }
474
475 if (serialNumber != nullptr)
476 {
477 aResp->res.jsonValue["SerialNumber"] =
478 *serialNumber;
479 }
480
481 if (manufacturer != nullptr)
482 {
483 aResp->res.jsonValue["Manufacturer"] =
484 *manufacturer;
485 }
486
487 if (model != nullptr)
488 {
489 aResp->res.jsonValue["Model"] = *model;
490 }
491
492 if (subModel != nullptr)
493 {
494 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700495 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500496
Ed Tanous002d39b2022-05-31 08:59:27 -0700497 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700498 sw_util::populateSoftwareInformation(
499 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200501 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700502
Ed Tanous002d39b2022-05-31 08:59:27 -0700503 sdbusplus::asio::getProperty<std::string>(
504 *crow::connections::systemBus, connection.first,
505 path,
506 "xyz.openbmc_project.Inventory.Decorator."
507 "AssetTag",
508 "AssetTag",
509 [aResp](const boost::system::error_code ec2,
510 const std::string& value) {
511 if (ec2)
512 {
513 // doesn't have to include this
514 // interface
515 return;
516 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700517
Ed Tanous002d39b2022-05-31 08:59:27 -0700518 aResp->res.jsonValue["AssetTag"] = value;
519 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700520 }
521 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200522 break;
Ed Tanous6c34de42018-08-29 13:37:36 -0700523 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700524 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700525 },
526 "xyz.openbmc_project.ObjectMapper",
527 "/xyz/openbmc_project/object_mapper",
528 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700529 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500530 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700531 "xyz.openbmc_project.Inventory.Decorator.Asset",
532 "xyz.openbmc_project.Inventory.Item.Cpu",
533 "xyz.openbmc_project.Inventory.Item.Dimm",
534 "xyz.openbmc_project.Inventory.Item.System",
535 "xyz.openbmc_project.Common.UUID",
536 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700537}
538
539/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 * @brief Retrieves host state properties over dbus
541 *
542 * @param[in] aResp Shared pointer for completing asynchronous calls.
543 *
544 * @return None.
545 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800546inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700547{
548 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700549 sdbusplus::asio::getProperty<std::string>(
550 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
551 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
552 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800553 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700554 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700555 if (ec)
556 {
557 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700558 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 // Service not available, no error, just don't return
560 // host state info
561 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700562 return;
563 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700564 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
565 messages::internalError(aResp->res);
566 return;
567 }
Ed Tanous66173382018-08-15 18:20:59 -0700568
Ed Tanous002d39b2022-05-31 08:59:27 -0700569 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
570 // Verify Host State
571 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
572 {
573 aResp->res.jsonValue["PowerState"] = "On";
574 aResp->res.jsonValue["Status"]["State"] = "Enabled";
575 }
576 else if (hostState ==
577 "xyz.openbmc_project.State.Host.HostState.Quiesced")
578 {
579 aResp->res.jsonValue["PowerState"] = "On";
580 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
581 }
582 else if (hostState ==
583 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
584 {
585 aResp->res.jsonValue["PowerState"] = "On";
586 aResp->res.jsonValue["Status"]["State"] = "InTest";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOn";
593 aResp->res.jsonValue["Status"]["State"] = "Starting";
594 }
595 else if (hostState ==
596 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
597 {
598 aResp->res.jsonValue["PowerState"] = "PoweringOff";
599 aResp->res.jsonValue["Status"]["State"] = "Disabled";
600 }
601 else
602 {
603 aResp->res.jsonValue["PowerState"] = "Off";
604 aResp->res.jsonValue["Status"]["State"] = "Disabled";
605 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700606 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700607}
608
609/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500610 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530611 *
612 * @param[in] dbusSource The boot source in DBUS speak.
613 *
614 * @return Returns as a string, the boot source in Redfish terms. If translation
615 * cannot be done, returns an empty string.
616 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000617inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530618{
619 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
620 {
621 return "None";
622 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700623 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530624 {
625 return "Hdd";
626 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700627 if (dbusSource ==
628 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530629 {
630 return "Cd";
631 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700632 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530633 {
634 return "Pxe";
635 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700636 if (dbusSource ==
637 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700638 {
639 return "Usb";
640 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700641 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530642}
643
644/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300645 * @brief Translates boot type DBUS property value to redfish.
646 *
647 * @param[in] dbusType The boot type in DBUS speak.
648 *
649 * @return Returns as a string, the boot type in Redfish terms. If translation
650 * cannot be done, returns an empty string.
651 */
652inline std::string dbusToRfBootType(const std::string& dbusType)
653{
654 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
655 {
656 return "Legacy";
657 }
658 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
659 {
660 return "UEFI";
661 }
662 return "";
663}
664
665/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500666 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530667 *
668 * @param[in] dbusMode The boot mode in DBUS speak.
669 *
670 * @return Returns as a string, the boot mode in Redfish terms. If translation
671 * cannot be done, returns an empty string.
672 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000673inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674{
675 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
676 {
677 return "None";
678 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700679 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530680 {
681 return "Diags";
682 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700683 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530684 {
685 return "BiosSetup";
686 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700687 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530688}
689
690/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600691 * @brief Translates boot progress DBUS property value to redfish.
692 *
693 * @param[in] dbusBootProgress The boot progress in DBUS speak.
694 *
695 * @return Returns as a string, the boot progress in Redfish terms. If
696 * translation cannot be done, returns "None".
697 */
698inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
699{
700 // Now convert the D-Bus BootProgress to the appropriate Redfish
701 // enum
702 std::string rfBpLastState = "None";
703 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
704 "ProgressStages.Unspecified")
705 {
706 rfBpLastState = "None";
707 }
708 else if (dbusBootProgress ==
709 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
710 "PrimaryProcInit")
711 {
712 rfBpLastState = "PrimaryProcessorInitializationStarted";
713 }
714 else if (dbusBootProgress ==
715 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
716 "BusInit")
717 {
718 rfBpLastState = "BusInitializationStarted";
719 }
720 else if (dbusBootProgress ==
721 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
722 "MemoryInit")
723 {
724 rfBpLastState = "MemoryInitializationStarted";
725 }
726 else if (dbusBootProgress ==
727 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
728 "SecondaryProcInit")
729 {
730 rfBpLastState = "SecondaryProcessorInitializationStarted";
731 }
732 else if (dbusBootProgress ==
733 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
734 "PCIInit")
735 {
736 rfBpLastState = "PCIResourceConfigStarted";
737 }
738 else if (dbusBootProgress ==
739 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
740 "SystemSetup")
741 {
742 rfBpLastState = "SetupEntered";
743 }
744 else if (dbusBootProgress ==
745 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
746 "SystemInitComplete")
747 {
748 rfBpLastState = "SystemHardwareInitializationComplete";
749 }
750 else if (dbusBootProgress ==
751 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
752 "OSStart")
753 {
754 rfBpLastState = "OSBootStarted";
755 }
756 else if (dbusBootProgress ==
757 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
758 "OSRunning")
759 {
760 rfBpLastState = "OSRunning";
761 }
762 else
763 {
764 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
765 << dbusBootProgress;
766 // Just return the default
767 }
768 return rfBpLastState;
769}
770
771/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500772 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 *
774 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700775 * @param[out] bootSource The DBus source
776 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700778 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530779 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800780inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500781 const std::string& rfSource,
782 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530783{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300784 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
785 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700786
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 if (rfSource == "None")
788 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700789 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530790 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700791 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530792 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700793 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
794 }
795 else if (rfSource == "Hdd")
796 {
797 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
798 }
799 else if (rfSource == "Diags")
800 {
801 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
802 }
803 else if (rfSource == "Cd")
804 {
805 bootSource =
806 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
807 }
808 else if (rfSource == "BiosSetup")
809 {
810 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530811 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700812 else if (rfSource == "Usb")
813 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700814 bootSource =
815 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700816 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530817 else
818 {
George Liu0fda0f12021-11-16 10:06:17 +0800819 BMCWEB_LOG_DEBUG
820 << "Invalid property value for BootSourceOverrideTarget: "
821 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700822 messages::propertyValueNotInList(aResp->res, rfSource,
823 "BootSourceTargetOverride");
824 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530825 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700826 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530827}
Ali Ahmed19817712021-06-29 17:01:52 -0500828
Andrew Geissler978b8802020-11-19 13:36:40 -0600829/**
830 * @brief Retrieves boot progress of the system
831 *
832 * @param[in] aResp Shared pointer for generating response message.
833 *
834 * @return None.
835 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800836inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600837{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700838 sdbusplus::asio::getProperty<std::string>(
839 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
840 "/xyz/openbmc_project/state/host0",
841 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600842 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700843 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700844 if (ec)
845 {
846 // BootProgress is an optional object so just do nothing if
847 // not found
848 return;
849 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600850
Ed Tanous002d39b2022-05-31 08:59:27 -0700851 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600852
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 aResp->res.jsonValue["BootProgress"]["LastState"] =
854 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700855 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600856}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530857
858/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300859 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300860 *
861 * @param[in] aResp Shared pointer for generating response message.
862 *
863 * @return None.
864 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300865
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300866inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300867{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700868 sdbusplus::asio::getProperty<std::string>(
869 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
870 "/xyz/openbmc_project/control/host0/boot",
871 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300872 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700873 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700874 if (ec)
875 {
876 // not an error, don't have to have the interface
877 return;
878 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300879
Ed Tanous002d39b2022-05-31 08:59:27 -0700880 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300881
Ed Tanous002d39b2022-05-31 08:59:27 -0700882 aResp->res.jsonValue["Boot"]
883 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
884 {"Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300885
Ed Tanous002d39b2022-05-31 08:59:27 -0700886 auto rfType = dbusToRfBootType(bootType);
887 if (rfType.empty())
888 {
889 messages::internalError(aResp->res);
890 return;
891 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300892
Ed Tanous002d39b2022-05-31 08:59:27 -0700893 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700894 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300895}
896
897/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300898 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530899 *
900 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530901 *
902 * @return None.
903 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300904
905inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530906{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700907 sdbusplus::asio::getProperty<std::string>(
908 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
909 "/xyz/openbmc_project/control/host0/boot",
910 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300911 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700912 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700913 if (ec)
914 {
915 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
916 messages::internalError(aResp->res);
917 return;
918 }
919
920 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
921
922 aResp->res
923 .jsonValue["Boot"]
924 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
925 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
926
927 if (bootModeStr !=
928 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
929 {
930 auto rfMode = dbusToRfBootMode(bootModeStr);
931 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530932 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700933 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
934 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530935 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700936 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700937 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938}
939
940/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300941 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530942 *
943 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
945 * @return None.
946 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300947
948inline void
949 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530950{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700951 sdbusplus::asio::getProperty<std::string>(
952 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
953 "/xyz/openbmc_project/control/host0/boot",
954 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300955 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700956 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700957 if (ec)
958 {
959 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000960 if (ec.value() == boost::asio::error::host_unreachable)
961 {
962 return;
963 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700964 messages::internalError(aResp->res);
965 return;
966 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967
Ed Tanous002d39b2022-05-31 08:59:27 -0700968 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969
Ed Tanous002d39b2022-05-31 08:59:27 -0700970 auto rfSource = dbusToRfBootSource(bootSourceStr);
971 if (!rfSource.empty())
972 {
973 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
974 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300975
Ed Tanous002d39b2022-05-31 08:59:27 -0700976 // Get BootMode as BootSourceOverrideTarget is constructed
977 // from both BootSource and BootMode
978 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700979 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530980}
981
982/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300983 * @brief This functions abstracts all the logic behind getting a
984 * "BootSourceOverrideEnabled" property from an overall boot override enable
985 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986 *
987 * @param[in] aResp Shared pointer for generating response message.
988 *
989 * @return None.
990 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530991
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300992inline void
993 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
994 const bool bootOverrideEnableSetting)
995{
996 if (!bootOverrideEnableSetting)
997 {
998 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
999 return;
1000 }
1001
1002 // If boot source override is enabled, we need to check 'one_time'
1003 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001004 sdbusplus::asio::getProperty<bool>(
1005 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1006 "/xyz/openbmc_project/control/host0/boot/one_time",
1007 "xyz.openbmc_project.Object.Enable", "Enabled",
1008 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001009 if (ec)
1010 {
1011 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1012 messages::internalError(aResp->res);
1013 return;
1014 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301015
Ed Tanous002d39b2022-05-31 08:59:27 -07001016 if (oneTimeSetting)
1017 {
1018 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1019 }
1020 else
1021 {
1022 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1023 "Continuous";
1024 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001025 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026}
1027
1028/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029 * @brief Retrieves boot override enable over DBUS
1030 *
1031 * @param[in] aResp Shared pointer for generating response message.
1032 *
1033 * @return None.
1034 */
1035
1036inline void
1037 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1038{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001039 sdbusplus::asio::getProperty<bool>(
1040 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1041 "/xyz/openbmc_project/control/host0/boot",
1042 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001044 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001045 if (ec)
1046 {
1047 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001048 if (ec.value() == boost::asio::error::host_unreachable)
1049 {
1050 return;
1051 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001052 messages::internalError(aResp->res);
1053 return;
1054 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001055
Ed Tanous002d39b2022-05-31 08:59:27 -07001056 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001057 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001058}
1059
1060/**
1061 * @brief Retrieves boot source override properties
1062 *
1063 * @param[in] aResp Shared pointer for generating response message.
1064 *
1065 * @return None.
1066 */
1067inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1068{
1069 BMCWEB_LOG_DEBUG << "Get boot information.";
1070
1071 getBootOverrideSource(aResp);
1072 getBootOverrideType(aResp);
1073 getBootOverrideEnable(aResp);
1074}
1075
1076/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001077 * @brief Retrieves the Last Reset Time
1078 *
1079 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1080 * and power off. Even though this is the "system" Redfish object look at the
1081 * chassis D-Bus interface for the LastStateChangeTime since this has the
1082 * last power operation time.
1083 *
1084 * @param[in] aResp Shared pointer for generating response message.
1085 *
1086 * @return None.
1087 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001088inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001089{
1090 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1091
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001092 sdbusplus::asio::getProperty<uint64_t>(
1093 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1094 "/xyz/openbmc_project/state/chassis0",
1095 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1096 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001097 if (ec)
1098 {
1099 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1100 return;
1101 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001102
Ed Tanous002d39b2022-05-31 08:59:27 -07001103 // LastStateChangeTime is epoch time, in milliseconds
1104 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1105 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001106
Ed Tanous002d39b2022-05-31 08:59:27 -07001107 // Convert to ISO 8601 standard
1108 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001109 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001110 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001111}
1112
1113/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001114 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1115 *
1116 * @param[in] aResp Shared pointer for generating response message.
1117 *
1118 * @return None.
1119 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001120inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001121{
1122 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1123
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001124 sdbusplus::asio::getProperty<bool>(
1125 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1126 "/xyz/openbmc_project/control/host0/auto_reboot",
1127 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1128 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001129 if (ec)
1130 {
1131 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1132 return;
1133 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001134
Ed Tanous002d39b2022-05-31 08:59:27 -07001135 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1136 if (autoRebootEnabled)
1137 {
1138 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1139 "RetryAttempts";
1140 // If AutomaticRetry (AutoReboot) is enabled see how many
1141 // attempts are left
1142 sdbusplus::asio::getProperty<uint32_t>(
1143 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1144 "/xyz/openbmc_project/state/host0",
1145 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1146 "AttemptsLeft",
1147 [aResp](const boost::system::error_code ec2,
1148 const uint32_t autoRebootAttemptsLeft) {
1149 if (ec2)
1150 {
1151 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1152 return;
1153 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001154
Ed Tanous002d39b2022-05-31 08:59:27 -07001155 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1156 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001157
Ed Tanous002d39b2022-05-31 08:59:27 -07001158 aResp->res
1159 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1160 autoRebootAttemptsLeft;
1161 });
1162 }
1163 else
1164 {
1165 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1166 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001167
Ed Tanous002d39b2022-05-31 08:59:27 -07001168 // Not on D-Bus. Hardcoded here:
1169 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1170 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001171
Ed Tanous002d39b2022-05-31 08:59:27 -07001172 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1173 // and RetryAttempts. OpenBMC only supports Disabled and
1174 // RetryAttempts.
1175 aResp->res.jsonValue["Boot"]
1176 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1177 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001178 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001179}
1180
1181/**
George Liuc6a620f2020-04-10 17:18:11 +08001182 * @brief Retrieves power restore policy over DBUS.
1183 *
1184 * @param[in] aResp Shared pointer for generating response message.
1185 *
1186 * @return None.
1187 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001188inline void
1189 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001190{
1191 BMCWEB_LOG_DEBUG << "Get power restore policy";
1192
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001193 sdbusplus::asio::getProperty<std::string>(
1194 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1195 "/xyz/openbmc_project/control/host0/power_restore_policy",
1196 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1197 [aResp](const boost::system::error_code ec, const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001198 if (ec)
1199 {
1200 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1201 return;
1202 }
George Liuc6a620f2020-04-10 17:18:11 +08001203
Ed Tanous002d39b2022-05-31 08:59:27 -07001204 const boost::container::flat_map<std::string, std::string> policyMaps = {
1205 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1206 "AlwaysOn"},
1207 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1208 "AlwaysOff"},
1209 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1210 "LastState"},
1211 // Return `AlwaysOff` when power restore policy set to "None"
1212 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1213 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001214
Ed Tanous002d39b2022-05-31 08:59:27 -07001215 auto policyMapsIt = policyMaps.find(policy);
1216 if (policyMapsIt == policyMaps.end())
1217 {
1218 messages::internalError(aResp->res);
1219 return;
1220 }
George Liuc6a620f2020-04-10 17:18:11 +08001221
Ed Tanous002d39b2022-05-31 08:59:27 -07001222 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001223 });
George Liuc6a620f2020-04-10 17:18:11 +08001224}
1225
1226/**
Ali Ahmed19817712021-06-29 17:01:52 -05001227 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1228 * TPM is required for booting the host.
1229 *
1230 * @param[in] aResp Shared pointer for generating response message.
1231 *
1232 * @return None.
1233 */
1234inline void getTrustedModuleRequiredToBoot(
1235 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1236{
1237 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1238
1239 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001240 [aResp](const boost::system::error_code ec,
1241 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001242 if (ec)
1243 {
1244 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1245 << ec;
1246 // This is an optional D-Bus object so just return if
1247 // error occurs
1248 return;
1249 }
1250 if (subtree.empty())
1251 {
1252 // As noted above, this is an optional interface so just return
1253 // if there is no instance found
1254 return;
1255 }
1256
1257 /* When there is more than one TPMEnable object... */
1258 if (subtree.size() > 1)
1259 {
1260 BMCWEB_LOG_DEBUG
1261 << "DBUS response has more than 1 TPM Enable object:"
1262 << subtree.size();
1263 // Throw an internal Error and return
1264 messages::internalError(aResp->res);
1265 return;
1266 }
1267
1268 // Make sure the Dbus response map has a service and objectPath
1269 // field
1270 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1271 {
1272 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1273 messages::internalError(aResp->res);
1274 return;
1275 }
1276
1277 const std::string& path = subtree[0].first;
1278 const std::string& serv = subtree[0].second.begin()->first;
1279
1280 // Valid TPM Enable object found, now reading the current value
1281 sdbusplus::asio::getProperty<bool>(
1282 *crow::connections::systemBus, serv, path,
1283 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous8a592812022-06-04 09:06:59 -07001284 [aResp](const boost::system::error_code ec2, bool tpmRequired) {
1285 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001286 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001287 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001288 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001289 messages::internalError(aResp->res);
1290 return;
1291 }
1292
Ed Tanous002d39b2022-05-31 08:59:27 -07001293 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001294 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001295 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1296 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001297 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001298 else
1299 {
1300 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1301 "Disabled";
1302 }
1303 });
Ali Ahmed19817712021-06-29 17:01:52 -05001304 },
1305 "xyz.openbmc_project.ObjectMapper",
1306 "/xyz/openbmc_project/object_mapper",
1307 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1308 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1309}
1310
1311/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001312 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1313 * TPM is required for booting the host.
1314 *
1315 * @param[in] aResp Shared pointer for generating response message.
1316 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1317 *
1318 * @return None.
1319 */
1320inline void setTrustedModuleRequiredToBoot(
1321 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1322{
1323 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1324
1325 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001326 [aResp, tpmRequired](const boost::system::error_code ec,
1327 dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001328 if (ec)
1329 {
1330 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1331 << ec;
1332 messages::internalError(aResp->res);
1333 return;
1334 }
1335 if (subtree.empty())
1336 {
1337 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1338 "TrustedModuleRequiredToBoot");
1339 return;
1340 }
1341
1342 /* When there is more than one TPMEnable object... */
1343 if (subtree.size() > 1)
1344 {
1345 BMCWEB_LOG_DEBUG
1346 << "DBUS response has more than 1 TPM Enable object:"
1347 << subtree.size();
1348 // Throw an internal Error and return
1349 messages::internalError(aResp->res);
1350 return;
1351 }
1352
1353 // Make sure the Dbus response map has a service and objectPath
1354 // field
1355 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1356 {
1357 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1358 messages::internalError(aResp->res);
1359 return;
1360 }
1361
1362 const std::string& path = subtree[0].first;
1363 const std::string& serv = subtree[0].second.begin()->first;
1364
1365 if (serv.empty())
1366 {
1367 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1368 messages::internalError(aResp->res);
1369 return;
1370 }
1371
1372 // Valid TPM Enable object found, now setting the value
1373 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07001374 [aResp](const boost::system::error_code ec2) {
1375 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001376 {
1377 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001378 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001379 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001380 messages::internalError(aResp->res);
1381 return;
1382 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001383 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1384 },
1385 serv, path, "org.freedesktop.DBus.Properties", "Set",
1386 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1387 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001388 },
1389 "xyz.openbmc_project.ObjectMapper",
1390 "/xyz/openbmc_project/object_mapper",
1391 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1392 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1393}
1394
1395/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301396 * @brief Sets boot properties into DBUS object(s).
1397 *
1398 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001399 * @param[in] bootType The boot type to set.
1400 * @return Integer error code.
1401 */
1402inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001403 const std::optional<std::string>& bootType)
1404{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001405 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001406
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001407 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001408 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001409 return;
1410 }
1411
1412 // Source target specified
1413 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1414 // Figure out which DBUS interface and property to use
1415 if (*bootType == "Legacy")
1416 {
1417 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1418 }
1419 else if (*bootType == "UEFI")
1420 {
1421 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1422 }
1423 else
1424 {
1425 BMCWEB_LOG_DEBUG << "Invalid property value for "
1426 "BootSourceOverrideMode: "
1427 << *bootType;
1428 messages::propertyValueNotInList(aResp->res, *bootType,
1429 "BootSourceOverrideMode");
1430 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001431 }
1432
1433 // Act on validated parameters
1434 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1435
1436 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001437 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001438 if (ec)
1439 {
1440 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1441 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001442 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001443 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001444 return;
1445 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001446 messages::internalError(aResp->res);
1447 return;
1448 }
1449 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001450 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001451 "xyz.openbmc_project.Settings",
1452 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001453 "org.freedesktop.DBus.Properties", "Set",
1454 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001455 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001456}
1457
1458/**
1459 * @brief Sets boot properties into DBUS object(s).
1460 *
1461 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001462 * @param[in] bootType The boot type to set.
1463 * @return Integer error code.
1464 */
1465inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1466 const std::optional<std::string>& bootEnable)
1467{
1468 if (!bootEnable)
1469 {
1470 return;
1471 }
1472 // Source target specified
1473 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1474
1475 bool bootOverrideEnable = false;
1476 bool bootOverridePersistent = false;
1477 // Figure out which DBUS interface and property to use
1478 if (*bootEnable == "Disabled")
1479 {
1480 bootOverrideEnable = false;
1481 }
1482 else if (*bootEnable == "Once")
1483 {
1484 bootOverrideEnable = true;
1485 bootOverridePersistent = false;
1486 }
1487 else if (*bootEnable == "Continuous")
1488 {
1489 bootOverrideEnable = true;
1490 bootOverridePersistent = true;
1491 }
1492 else
1493 {
George Liu0fda0f12021-11-16 10:06:17 +08001494 BMCWEB_LOG_DEBUG
1495 << "Invalid property value for BootSourceOverrideEnabled: "
1496 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001497 messages::propertyValueNotInList(aResp->res, *bootEnable,
1498 "BootSourceOverrideEnabled");
1499 return;
1500 }
1501
1502 // Act on validated parameters
1503 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1504
1505 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07001506 [aResp](const boost::system::error_code ec2) {
1507 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001508 {
Ed Tanous8a592812022-06-04 09:06:59 -07001509 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001510 messages::internalError(aResp->res);
1511 return;
1512 }
1513 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001514 },
1515 "xyz.openbmc_project.Settings",
1516 "/xyz/openbmc_project/control/host0/boot",
1517 "org.freedesktop.DBus.Properties", "Set",
1518 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001519 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001520
1521 if (!bootOverrideEnable)
1522 {
1523 return;
1524 }
1525
1526 // In case boot override is enabled we need to set correct value for the
1527 // 'one_time' enable DBus interface
1528 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1529 << bootOverridePersistent;
1530
1531 crow::connections::systemBus->async_method_call(
1532 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001533 if (ec)
1534 {
1535 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1536 messages::internalError(aResp->res);
1537 return;
1538 }
1539 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001540 },
1541 "xyz.openbmc_project.Settings",
1542 "/xyz/openbmc_project/control/host0/boot/one_time",
1543 "org.freedesktop.DBus.Properties", "Set",
1544 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001545 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001546}
1547
1548/**
1549 * @brief Sets boot properties into DBUS object(s).
1550 *
1551 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301552 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301553 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001554 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301555 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001556inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001557 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301558{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001559 std::string bootSourceStr;
1560 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001561
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001562 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301563 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001564 return;
1565 }
1566
1567 // Source target specified
1568 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1569 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001570 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1571 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001572 {
1573 BMCWEB_LOG_DEBUG
1574 << "Invalid property value for BootSourceOverrideTarget: "
1575 << *bootSource;
1576 messages::propertyValueNotInList(aResp->res, *bootSource,
1577 "BootSourceTargetOverride");
1578 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001579 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301580
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001581 // Act on validated parameters
1582 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1583 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001584
1585 crow::connections::systemBus->async_method_call(
1586 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001587 if (ec)
1588 {
1589 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1590 messages::internalError(aResp->res);
1591 return;
1592 }
1593 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001594 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001595 "xyz.openbmc_project.Settings",
1596 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001597 "org.freedesktop.DBus.Properties", "Set",
1598 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001599 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001600
1601 crow::connections::systemBus->async_method_call(
1602 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001603 if (ec)
1604 {
1605 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1606 messages::internalError(aResp->res);
1607 return;
1608 }
1609 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001610 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001611 "xyz.openbmc_project.Settings",
1612 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001613 "org.freedesktop.DBus.Properties", "Set",
1614 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001615 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001616}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001617
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001618/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001619 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301620 *
1621 * @param[in] aResp Shared pointer for generating response message.
1622 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001623 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301624 * @param[in] bootEnable The boot override enable from incoming RF request.
1625 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001626 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301627 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001628
1629inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1630 const std::optional<std::string>& bootSource,
1631 const std::optional<std::string>& bootType,
1632 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301633{
1634 BMCWEB_LOG_DEBUG << "Set boot information.";
1635
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001636 setBootModeOrSource(aResp, bootSource);
1637 setBootType(aResp, bootType);
1638 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301639}
1640
George Liuc6a620f2020-04-10 17:18:11 +08001641/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001642 * @brief Sets AssetTag
1643 *
1644 * @param[in] aResp Shared pointer for generating response message.
1645 * @param[in] assetTag "AssetTag" from request.
1646 *
1647 * @return None.
1648 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001649inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001650 const std::string& assetTag)
1651{
1652 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001653 [aResp,
1654 assetTag](const boost::system::error_code ec,
1655 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001656 if (ec)
1657 {
1658 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1659 messages::internalError(aResp->res);
1660 return;
1661 }
1662 if (subtree.empty())
1663 {
1664 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1665 messages::internalError(aResp->res);
1666 return;
1667 }
1668 // Assume only 1 system D-Bus object
1669 // Throw an error if there is more than 1
1670 if (subtree.size() > 1)
1671 {
1672 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1673 messages::internalError(aResp->res);
1674 return;
1675 }
1676 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1677 {
1678 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1679 messages::internalError(aResp->res);
1680 return;
1681 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001682
Ed Tanous002d39b2022-05-31 08:59:27 -07001683 const std::string& path = subtree[0].first;
1684 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001685
Ed Tanous002d39b2022-05-31 08:59:27 -07001686 if (service.empty())
1687 {
1688 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1689 messages::internalError(aResp->res);
1690 return;
1691 }
1692
1693 crow::connections::systemBus->async_method_call(
1694 [aResp](const boost::system::error_code ec2) {
1695 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001696 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001697 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1698 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001699 messages::internalError(aResp->res);
1700 return;
1701 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001702 },
1703 service, path, "org.freedesktop.DBus.Properties", "Set",
1704 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1705 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001706 },
1707 "xyz.openbmc_project.ObjectMapper",
1708 "/xyz/openbmc_project/object_mapper",
1709 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1710 "/xyz/openbmc_project/inventory", int32_t(0),
1711 std::array<const char*, 1>{
1712 "xyz.openbmc_project.Inventory.Item.System"});
1713}
1714
1715/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001716 * @brief Sets automaticRetry (Auto Reboot)
1717 *
1718 * @param[in] aResp Shared pointer for generating response message.
1719 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1720 *
1721 * @return None.
1722 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001723inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001724 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001725{
1726 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1727
1728 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001729 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001730
1731 if (automaticRetryConfig == "Disabled")
1732 {
1733 autoRebootEnabled = false;
1734 }
1735 else if (automaticRetryConfig == "RetryAttempts")
1736 {
1737 autoRebootEnabled = true;
1738 }
1739 else
1740 {
George Liu0fda0f12021-11-16 10:06:17 +08001741 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001742 << automaticRetryConfig;
1743 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1744 "AutomaticRetryConfig");
1745 return;
1746 }
1747
1748 crow::connections::systemBus->async_method_call(
1749 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001750 if (ec)
1751 {
1752 messages::internalError(aResp->res);
1753 return;
1754 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001755 },
1756 "xyz.openbmc_project.Settings",
1757 "/xyz/openbmc_project/control/host0/auto_reboot",
1758 "org.freedesktop.DBus.Properties", "Set",
1759 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001760 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001761}
1762
1763/**
George Liuc6a620f2020-04-10 17:18:11 +08001764 * @brief Sets power restore policy properties.
1765 *
1766 * @param[in] aResp Shared pointer for generating response message.
1767 * @param[in] policy power restore policy properties from request.
1768 *
1769 * @return None.
1770 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001771inline void
1772 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1773 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001774{
1775 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1776
1777 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001778 {"AlwaysOn",
1779 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1780 {"AlwaysOff",
1781 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1782 {"LastState",
1783 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001784
1785 std::string powerRestorPolicy;
1786
Gunnar Mills4e69c902021-01-05 19:50:11 -06001787 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001788 if (policyMapsIt == policyMaps.end())
1789 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001790 messages::propertyValueNotInList(aResp->res, policy,
1791 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001792 return;
1793 }
1794
1795 powerRestorPolicy = policyMapsIt->second;
1796
1797 crow::connections::systemBus->async_method_call(
1798 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001799 if (ec)
1800 {
1801 messages::internalError(aResp->res);
1802 return;
1803 }
George Liuc6a620f2020-04-10 17:18:11 +08001804 },
1805 "xyz.openbmc_project.Settings",
1806 "/xyz/openbmc_project/control/host0/power_restore_policy",
1807 "org.freedesktop.DBus.Properties", "Set",
1808 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001809 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001810}
1811
AppaRao Pulia6349912019-10-18 17:16:08 +05301812#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1813/**
1814 * @brief Retrieves provisioning status
1815 *
1816 * @param[in] aResp Shared pointer for completing asynchronous calls.
1817 *
1818 * @return None.
1819 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001820inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301821{
1822 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001823 sdbusplus::asio::getAllProperties(
1824 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1825 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
AppaRao Pulia6349912019-10-18 17:16:08 +05301826 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001827 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001828 nlohmann::json& oemPFR =
1829 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1830 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1831 "#OemComputerSystem.OpenBmc";
1832 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001833
Ed Tanous002d39b2022-05-31 08:59:27 -07001834 if (ec)
1835 {
1836 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1837 // not an error, don't have to have the interface
1838 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1839 return;
1840 }
1841
1842 const bool* provState = nullptr;
1843 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001844
1845 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001846 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1847 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001848
1849 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001850 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001851 messages::internalError(aResp->res);
1852 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001853 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301854
Ed Tanous002d39b2022-05-31 08:59:27 -07001855 if ((provState == nullptr) || (lockState == nullptr))
1856 {
1857 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1858 messages::internalError(aResp->res);
1859 return;
1860 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301861
Ed Tanous002d39b2022-05-31 08:59:27 -07001862 if (*provState == true)
1863 {
1864 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301865 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001866 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301867 }
1868 else
1869 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001870 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301871 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001872 }
1873 else
1874 {
1875 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1876 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001877 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301878}
1879#endif
1880
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301881/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001882 * @brief Translate the PowerMode to a response message.
1883 *
1884 * @param[in] aResp Shared pointer for generating response message.
1885 * @param[in] modeValue PowerMode value to be translated
1886 *
1887 * @return None.
1888 */
1889inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1890 const std::string& modeValue)
1891{
George Liu0fda0f12021-11-16 10:06:17 +08001892 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001893 {
1894 aResp->res.jsonValue["PowerMode"] = "Static";
1895 }
George Liu0fda0f12021-11-16 10:06:17 +08001896 else if (
1897 modeValue ==
1898 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001899 {
1900 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1901 }
George Liu0fda0f12021-11-16 10:06:17 +08001902 else if (modeValue ==
1903 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001904 {
1905 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1906 }
George Liu0fda0f12021-11-16 10:06:17 +08001907 else if (modeValue ==
1908 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001909 {
1910 aResp->res.jsonValue["PowerMode"] = "OEM";
1911 }
1912 else
1913 {
1914 // Any other values would be invalid
1915 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1916 messages::internalError(aResp->res);
1917 }
1918}
1919
1920/**
1921 * @brief Retrieves system power mode
1922 *
1923 * @param[in] aResp Shared pointer for generating response message.
1924 *
1925 * @return None.
1926 */
1927inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1928{
1929 BMCWEB_LOG_DEBUG << "Get power mode.";
1930
1931 // Get Power Mode object path:
1932 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001933 [aResp](const boost::system::error_code ec,
1934 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001935 if (ec)
1936 {
1937 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
1938 << ec;
1939 // This is an optional D-Bus object so just return if
1940 // error occurs
1941 return;
1942 }
1943 if (subtree.empty())
1944 {
1945 // As noted above, this is an optional interface so just return
1946 // if there is no instance found
1947 return;
1948 }
1949 if (subtree.size() > 1)
1950 {
1951 // More then one PowerMode object is not supported and is an
1952 // error
1953 BMCWEB_LOG_DEBUG
1954 << "Found more than 1 system D-Bus Power.Mode objects: "
1955 << subtree.size();
1956 messages::internalError(aResp->res);
1957 return;
1958 }
1959 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1960 {
1961 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1962 messages::internalError(aResp->res);
1963 return;
1964 }
1965 const std::string& path = subtree[0].first;
1966 const std::string& service = subtree[0].second.begin()->first;
1967 if (service.empty())
1968 {
1969 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1970 messages::internalError(aResp->res);
1971 return;
1972 }
1973 // Valid Power Mode object found, now read the current value
1974 sdbusplus::asio::getProperty<std::string>(
1975 *crow::connections::systemBus, service, path,
1976 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous8a592812022-06-04 09:06:59 -07001977 [aResp](const boost::system::error_code ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07001978 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07001979 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05001980 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001981 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07001982 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05001983 messages::internalError(aResp->res);
1984 return;
1985 }
Chris Cain3a2d04242021-05-28 16:57:10 -05001986
Ed Tanous002d39b2022-05-31 08:59:27 -07001987 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
1988 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05001989
Ed Tanous002d39b2022-05-31 08:59:27 -07001990 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1991 translatePowerMode(aResp, pmode);
1992 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001993 },
1994 "xyz.openbmc_project.ObjectMapper",
1995 "/xyz/openbmc_project/object_mapper",
1996 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1997 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1998}
1999
2000/**
2001 * @brief Validate the specified mode is valid and return the PowerMode
2002 * name associated with that string
2003 *
2004 * @param[in] aResp Shared pointer for generating response message.
2005 * @param[in] modeString String representing the desired PowerMode
2006 *
2007 * @return PowerMode value or empty string if mode is not valid
2008 */
2009inline std::string
2010 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2011 const std::string& modeString)
2012{
2013 std::string mode;
2014
2015 if (modeString == "Static")
2016 {
2017 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2018 }
2019 else if (modeString == "MaximumPerformance")
2020 {
George Liu0fda0f12021-11-16 10:06:17 +08002021 mode =
2022 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002023 }
2024 else if (modeString == "PowerSaving")
2025 {
2026 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2027 }
2028 else
2029 {
2030 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2031 }
2032 return mode;
2033}
2034
2035/**
2036 * @brief Sets system power mode.
2037 *
2038 * @param[in] aResp Shared pointer for generating response message.
2039 * @param[in] pmode System power mode from request.
2040 *
2041 * @return None.
2042 */
2043inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2044 const std::string& pmode)
2045{
2046 BMCWEB_LOG_DEBUG << "Set power mode.";
2047
2048 std::string powerMode = validatePowerMode(aResp, pmode);
2049 if (powerMode.empty())
2050 {
2051 return;
2052 }
2053
2054 // Get Power Mode object path:
2055 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002056 [aResp,
2057 powerMode](const boost::system::error_code ec,
2058 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002059 if (ec)
2060 {
2061 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2062 << ec;
2063 // This is an optional D-Bus object, but user attempted to patch
2064 messages::internalError(aResp->res);
2065 return;
2066 }
2067 if (subtree.empty())
2068 {
2069 // This is an optional D-Bus object, but user attempted to patch
2070 messages::resourceNotFound(aResp->res, "ComputerSystem",
2071 "PowerMode");
2072 return;
2073 }
2074 if (subtree.size() > 1)
2075 {
2076 // More then one PowerMode object is not supported and is an
2077 // error
2078 BMCWEB_LOG_DEBUG
2079 << "Found more than 1 system D-Bus Power.Mode objects: "
2080 << subtree.size();
2081 messages::internalError(aResp->res);
2082 return;
2083 }
2084 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2085 {
2086 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2087 messages::internalError(aResp->res);
2088 return;
2089 }
2090 const std::string& path = subtree[0].first;
2091 const std::string& service = subtree[0].second.begin()->first;
2092 if (service.empty())
2093 {
2094 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2095 messages::internalError(aResp->res);
2096 return;
2097 }
2098
2099 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2100 << path;
2101
2102 // Set the Power Mode property
2103 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002104 [aResp](const boost::system::error_code ec2) {
2105 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002106 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002107 messages::internalError(aResp->res);
2108 return;
2109 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002110 },
2111 service, path, "org.freedesktop.DBus.Properties", "Set",
2112 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2113 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002114 },
2115 "xyz.openbmc_project.ObjectMapper",
2116 "/xyz/openbmc_project/object_mapper",
2117 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2118 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2119}
2120
2121/**
Yong Li51709ff2019-09-30 14:13:04 +08002122 * @brief Translates watchdog timeout action DBUS property value to redfish.
2123 *
2124 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2125 *
2126 * @return Returns as a string, the timeout action in Redfish terms. If
2127 * translation cannot be done, returns an empty string.
2128 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002129inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002130{
2131 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2132 {
2133 return "None";
2134 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002135 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002136 {
2137 return "ResetSystem";
2138 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002139 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002140 {
2141 return "PowerDown";
2142 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002143 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002144 {
2145 return "PowerCycle";
2146 }
2147
2148 return "";
2149}
2150
2151/**
Yong Lic45f0082019-10-10 14:19:01 +08002152 *@brief Translates timeout action from Redfish to DBUS property value.
2153 *
2154 *@param[in] rfAction The timeout action in Redfish.
2155 *
2156 *@return Returns as a string, the time_out action as expected by DBUS.
2157 *If translation cannot be done, returns an empty string.
2158 */
2159
Ed Tanous23a21a12020-07-25 04:45:05 +00002160inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002161{
2162 if (rfAction == "None")
2163 {
2164 return "xyz.openbmc_project.State.Watchdog.Action.None";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002167 {
2168 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002170 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002171 {
2172 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2173 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002174 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002175 {
2176 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2177 }
2178
2179 return "";
2180}
2181
2182/**
Yong Li51709ff2019-09-30 14:13:04 +08002183 * @brief Retrieves host watchdog timer properties over DBUS
2184 *
2185 * @param[in] aResp Shared pointer for completing asynchronous calls.
2186 *
2187 * @return None.
2188 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002189inline void
2190 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002191{
2192 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002193 sdbusplus::asio::getAllProperties(
2194 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2195 "/xyz/openbmc_project/watchdog/host0",
2196 "xyz.openbmc_project.State.Watchdog",
Yong Li51709ff2019-09-30 14:13:04 +08002197 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002198 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002199 if (ec)
2200 {
2201 // watchdog service is stopped
2202 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2203 return;
2204 }
2205
2206 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2207
2208 nlohmann::json& hostWatchdogTimer =
2209 aResp->res.jsonValue["HostWatchdogTimer"];
2210
2211 // watchdog service is running/enabled
2212 hostWatchdogTimer["Status"]["State"] = "Enabled";
2213
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002214 const bool* enabled = nullptr;
2215 const std::string* expireAction = nullptr;
2216
2217 const bool success = sdbusplus::unpackPropertiesNoThrow(
2218 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2219 "ExpireAction", expireAction);
2220
2221 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002222 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002223 messages::internalError(aResp->res);
2224 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002225 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002226
2227 if (enabled != nullptr)
2228 {
2229 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2230 }
2231
2232 if (expireAction != nullptr)
2233 {
2234 std::string action = dbusToRfWatchdogAction(*expireAction);
2235 if (action.empty())
2236 {
2237 messages::internalError(aResp->res);
2238 return;
2239 }
2240 hostWatchdogTimer["TimeoutAction"] = action;
2241 }
2242 });
Yong Li51709ff2019-09-30 14:13:04 +08002243}
2244
2245/**
Yong Lic45f0082019-10-10 14:19:01 +08002246 * @brief Sets Host WatchDog Timer properties.
2247 *
2248 * @param[in] aResp Shared pointer for generating response message.
2249 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2250 * RF request.
2251 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2252 *
2253 * @return None.
2254 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002255inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002256 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002257 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002258{
2259 BMCWEB_LOG_DEBUG << "Set host watchdog";
2260
2261 if (wdtTimeOutAction)
2262 {
2263 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2264 // check if TimeOut Action is Valid
2265 if (wdtTimeOutActStr.empty())
2266 {
2267 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2268 << *wdtTimeOutAction;
2269 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2270 "TimeoutAction");
2271 return;
2272 }
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", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002287 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002288 }
2289
2290 if (wdtEnable)
2291 {
2292 crow::connections::systemBus->async_method_call(
2293 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002294 if (ec)
2295 {
2296 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2297 messages::internalError(aResp->res);
2298 return;
2299 }
Yong Lic45f0082019-10-10 14:19:01 +08002300 },
2301 "xyz.openbmc_project.Watchdog",
2302 "/xyz/openbmc_project/watchdog/host0",
2303 "org.freedesktop.DBus.Properties", "Set",
2304 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002305 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002306 }
2307}
2308
Chris Cain37bbf982021-09-20 10:53:09 -05002309/**
2310 * @brief Parse the Idle Power Saver properties into json
2311 *
2312 * @param[in] aResp Shared pointer for completing asynchronous calls.
2313 * @param[in] properties IPS property data from DBus.
2314 *
2315 * @return true if successful
2316 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002317inline bool
2318 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2319 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002320{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002321 const bool* enabled = nullptr;
2322 const uint8_t* enterUtilizationPercent = nullptr;
2323 const uint64_t* enterDwellTime = nullptr;
2324 const uint8_t* exitUtilizationPercent = nullptr;
2325 const uint64_t* exitDwellTime = nullptr;
2326
2327 const bool success = sdbusplus::unpackPropertiesNoThrow(
2328 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2329 "EnterUtilizationPercent", enterUtilizationPercent,
2330 "ExitUtilizationPercent", exitUtilizationPercent, "ExitDwellTime",
2331 exitDwellTime);
2332
2333 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002334 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002335 return false;
2336 }
2337
2338 if (enabled != nullptr)
2339 {
2340 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2341 }
2342
2343 if (enterUtilizationPercent != nullptr)
2344 {
2345 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2346 *enterUtilizationPercent;
2347 }
2348
2349 if (enterDwellTime != nullptr)
2350 {
2351 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2352 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2353 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2354 .count();
2355 }
2356
2357 if (exitUtilizationPercent != nullptr)
2358 {
2359 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2360 *exitUtilizationPercent;
2361 }
2362
2363 if (exitDwellTime != nullptr)
2364 {
2365 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2366 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2367 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2368 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002369 }
2370
2371 return true;
2372}
2373
2374/**
2375 * @brief Retrieves host watchdog timer properties over DBUS
2376 *
2377 * @param[in] aResp Shared pointer for completing asynchronous calls.
2378 *
2379 * @return None.
2380 */
2381inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2382{
2383 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2384
2385 // Get IdlePowerSaver object path:
2386 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002387 [aResp](const boost::system::error_code ec,
2388 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002389 if (ec)
2390 {
2391 BMCWEB_LOG_DEBUG
2392 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2393 << ec;
2394 messages::internalError(aResp->res);
2395 return;
2396 }
2397 if (subtree.empty())
2398 {
2399 // This is an optional interface so just return
2400 // if there is no instance found
2401 BMCWEB_LOG_DEBUG << "No instances found";
2402 return;
2403 }
2404 if (subtree.size() > 1)
2405 {
2406 // More then one PowerIdlePowerSaver object is not supported and
2407 // is an error
2408 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2409 "Power.IdlePowerSaver objects: "
2410 << subtree.size();
2411 messages::internalError(aResp->res);
2412 return;
2413 }
2414 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2415 {
2416 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2417 messages::internalError(aResp->res);
2418 return;
2419 }
2420 const std::string& path = subtree[0].first;
2421 const std::string& service = subtree[0].second.begin()->first;
2422 if (service.empty())
2423 {
2424 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2425 messages::internalError(aResp->res);
2426 return;
2427 }
2428
2429 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002430 sdbusplus::asio::getAllProperties(
2431 *crow::connections::systemBus, service, path,
2432 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous8a592812022-06-04 09:06:59 -07002433 [aResp](const boost::system::error_code ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002434 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002435 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002436 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002437 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002438 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002439 messages::internalError(aResp->res);
2440 return;
2441 }
2442
Ed Tanous002d39b2022-05-31 08:59:27 -07002443 if (!parseIpsProperties(aResp, properties))
2444 {
2445 messages::internalError(aResp->res);
2446 return;
2447 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002448 });
Chris Cain37bbf982021-09-20 10:53:09 -05002449 },
2450 "xyz.openbmc_project.ObjectMapper",
2451 "/xyz/openbmc_project/object_mapper",
2452 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2453 std::array<const char*, 1>{
2454 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2455
2456 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2457}
2458
2459/**
2460 * @brief Sets Idle Power Saver properties.
2461 *
2462 * @param[in] aResp Shared pointer for generating response message.
2463 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2464 * RF request.
2465 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2466 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2467 * before entering idle state.
2468 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2469 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2470 * before exiting idle state
2471 *
2472 * @return None.
2473 */
2474inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2475 const std::optional<bool> ipsEnable,
2476 const std::optional<uint8_t> ipsEnterUtil,
2477 const std::optional<uint64_t> ipsEnterTime,
2478 const std::optional<uint8_t> ipsExitUtil,
2479 const std::optional<uint64_t> ipsExitTime)
2480{
2481 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2482
2483 // Get IdlePowerSaver object path:
2484 crow::connections::systemBus->async_method_call(
2485 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002486 ipsExitTime](const boost::system::error_code ec,
2487 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002488 if (ec)
2489 {
2490 BMCWEB_LOG_DEBUG
2491 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2492 << ec;
2493 messages::internalError(aResp->res);
2494 return;
2495 }
2496 if (subtree.empty())
2497 {
2498 // This is an optional D-Bus object, but user attempted to patch
2499 messages::resourceNotFound(aResp->res, "ComputerSystem",
2500 "IdlePowerSaver");
2501 return;
2502 }
2503 if (subtree.size() > 1)
2504 {
2505 // More then one PowerIdlePowerSaver object is not supported and
2506 // is an error
2507 BMCWEB_LOG_DEBUG
2508 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2509 << subtree.size();
2510 messages::internalError(aResp->res);
2511 return;
2512 }
2513 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2514 {
2515 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2516 messages::internalError(aResp->res);
2517 return;
2518 }
2519 const std::string& path = subtree[0].first;
2520 const std::string& service = subtree[0].second.begin()->first;
2521 if (service.empty())
2522 {
2523 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2524 messages::internalError(aResp->res);
2525 return;
2526 }
Chris Cain37bbf982021-09-20 10:53:09 -05002527
Ed Tanous002d39b2022-05-31 08:59:27 -07002528 // Valid Power IdlePowerSaver object found, now set any values that
2529 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002530
Ed Tanous002d39b2022-05-31 08:59:27 -07002531 if (ipsEnable)
2532 {
2533 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002534 [aResp](const boost::system::error_code ec2) {
2535 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002536 {
Ed Tanous8a592812022-06-04 09:06:59 -07002537 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002538 messages::internalError(aResp->res);
2539 return;
2540 }
2541 },
2542 service, path, "org.freedesktop.DBus.Properties", "Set",
2543 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2544 dbus::utility::DbusVariantType(*ipsEnable));
2545 }
2546 if (ipsEnterUtil)
2547 {
2548 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002549 [aResp](const boost::system::error_code ec2) {
2550 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002551 {
Ed Tanous8a592812022-06-04 09:06:59 -07002552 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002553 messages::internalError(aResp->res);
2554 return;
2555 }
2556 },
2557 service, path, "org.freedesktop.DBus.Properties", "Set",
2558 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2559 "EnterUtilizationPercent",
2560 dbus::utility::DbusVariantType(*ipsEnterUtil));
2561 }
2562 if (ipsEnterTime)
2563 {
2564 // Convert from seconds into milliseconds for DBus
2565 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2566 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002567 [aResp](const boost::system::error_code ec2) {
2568 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002569 {
Ed Tanous8a592812022-06-04 09:06:59 -07002570 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002571 messages::internalError(aResp->res);
2572 return;
2573 }
2574 },
2575 service, path, "org.freedesktop.DBus.Properties", "Set",
2576 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2577 "EnterDwellTime",
2578 dbus::utility::DbusVariantType(timeMilliseconds));
2579 }
2580 if (ipsExitUtil)
2581 {
2582 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002583 [aResp](const boost::system::error_code ec2) {
2584 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002585 {
Ed Tanous8a592812022-06-04 09:06:59 -07002586 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002587 messages::internalError(aResp->res);
2588 return;
2589 }
2590 },
2591 service, path, "org.freedesktop.DBus.Properties", "Set",
2592 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2593 "ExitUtilizationPercent",
2594 dbus::utility::DbusVariantType(*ipsExitUtil));
2595 }
2596 if (ipsExitTime)
2597 {
2598 // Convert from seconds into milliseconds for DBus
2599 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2600 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002601 [aResp](const boost::system::error_code ec2) {
2602 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002603 {
Ed Tanous8a592812022-06-04 09:06:59 -07002604 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002605 messages::internalError(aResp->res);
2606 return;
2607 }
2608 },
2609 service, path, "org.freedesktop.DBus.Properties", "Set",
2610 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2611 "ExitDwellTime",
2612 dbus::utility::DbusVariantType(timeMilliseconds));
2613 }
Chris Cain37bbf982021-09-20 10:53:09 -05002614 },
2615 "xyz.openbmc_project.ObjectMapper",
2616 "/xyz/openbmc_project/object_mapper",
2617 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2618 std::array<const char*, 1>{
2619 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2620
2621 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2622}
2623
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002624inline void handleComputerSystemHead(
2625 crow::App& app, const crow::Request& req,
2626 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2627{
2628 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2629 {
2630 return;
2631 }
2632 asyncResp->res.addHeader(
2633 boost::beast::http::field::link,
2634 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2635}
2636
Yong Lic45f0082019-10-10 14:19:01 +08002637/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002638 * SystemsCollection derived class for delivering ComputerSystems Collection
2639 * Schema
2640 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002641inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002642{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002643 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002644 .privileges(redfish::privileges::headComputerSystemCollection)
2645 .methods(boost::beast::http::verb::head)(
2646 std::bind_front(handleComputerSystemHead, std::ref(app)));
2647
2648 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002649 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002650 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002651 [&app](const crow::Request& req,
2652 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002653 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002654 {
2655 return;
2656 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002657
2658 asyncResp->res.addHeader(
2659 boost::beast::http::field::link,
2660 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002661 asyncResp->res.jsonValue["@odata.type"] =
2662 "#ComputerSystemCollection.ComputerSystemCollection";
2663 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2664 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002665
Ed Tanous002d39b2022-05-31 08:59:27 -07002666 sdbusplus::asio::getProperty<std::string>(
2667 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2668 "/xyz/openbmc_project/network/hypervisor",
2669 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous8a592812022-06-04 09:06:59 -07002670 [asyncResp](const boost::system::error_code ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002671 const std::string& /*hostName*/) {
2672 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2673 ifaceArray = nlohmann::json::array();
2674 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002675
Ed Tanous002d39b2022-05-31 08:59:27 -07002676 nlohmann::json::object_t system;
2677 system["@odata.id"] = "/redfish/v1/Systems/system";
2678 ifaceArray.push_back(std::move(system));
2679 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002680 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002681 {
2682 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2683 nlohmann::json::object_t hypervisor;
2684 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2685 ifaceArray.push_back(std::move(hypervisor));
2686 count = ifaceArray.size();
2687 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002688 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002689 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002690}
Sunitha Harish462023a2020-02-19 08:34:59 -06002691
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002692/**
2693 * Function transceives data with dbus directly.
2694 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002695inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002696{
2697 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2698 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2699 constexpr char const* interfaceName =
2700 "xyz.openbmc_project.Control.Host.NMI";
2701 constexpr char const* method = "NMI";
2702
2703 crow::connections::systemBus->async_method_call(
2704 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002705 if (ec)
2706 {
2707 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2708 messages::internalError(asyncResp->res);
2709 return;
2710 }
2711 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002712 },
2713 serviceName, objectPath, interfaceName, method);
2714}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002715
2716/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002717 * SystemActionsReset class supports handle POST method for Reset action.
2718 * The class retrieves and sends data directly to D-Bus.
2719 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002720inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002721{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002722 /**
2723 * Function handles POST method request.
2724 * Analyzes POST body message before sends Reset request data to D-Bus.
2725 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002726 BMCWEB_ROUTE(app,
2727 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002728 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002729 .methods(boost::beast::http::verb::post)(
2730 [&app](const crow::Request& req,
2731 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002732 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002733 {
2734 return;
2735 }
2736 std::string resetType;
2737 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2738 resetType))
2739 {
2740 return;
2741 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002742
Ed Tanous002d39b2022-05-31 08:59:27 -07002743 // Get the command and host vs. chassis
2744 std::string command;
2745 bool hostCommand = true;
2746 if ((resetType == "On") || (resetType == "ForceOn"))
2747 {
2748 command = "xyz.openbmc_project.State.Host.Transition.On";
2749 hostCommand = true;
2750 }
2751 else if (resetType == "ForceOff")
2752 {
2753 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2754 hostCommand = false;
2755 }
2756 else if (resetType == "ForceRestart")
2757 {
2758 command =
2759 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2760 hostCommand = true;
2761 }
2762 else if (resetType == "GracefulShutdown")
2763 {
2764 command = "xyz.openbmc_project.State.Host.Transition.Off";
2765 hostCommand = true;
2766 }
2767 else if (resetType == "GracefulRestart")
2768 {
2769 command =
2770 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2771 hostCommand = true;
2772 }
2773 else if (resetType == "PowerCycle")
2774 {
2775 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2776 hostCommand = true;
2777 }
2778 else if (resetType == "Nmi")
2779 {
2780 doNMI(asyncResp);
2781 return;
2782 }
2783 else
2784 {
2785 messages::actionParameterUnknown(asyncResp->res, "Reset",
2786 resetType);
2787 return;
2788 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002789
Ed Tanous002d39b2022-05-31 08:59:27 -07002790 if (hostCommand)
2791 {
2792 crow::connections::systemBus->async_method_call(
2793 [asyncResp, resetType](const boost::system::error_code ec) {
2794 if (ec)
2795 {
2796 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2797 if (ec.value() == boost::asio::error::invalid_argument)
2798 {
2799 messages::actionParameterNotSupported(
2800 asyncResp->res, resetType, "Reset");
2801 }
2802 else
2803 {
2804 messages::internalError(asyncResp->res);
2805 }
2806 return;
2807 }
2808 messages::success(asyncResp->res);
2809 },
2810 "xyz.openbmc_project.State.Host",
2811 "/xyz/openbmc_project/state/host0",
2812 "org.freedesktop.DBus.Properties", "Set",
2813 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2814 dbus::utility::DbusVariantType{command});
2815 }
2816 else
2817 {
2818 crow::connections::systemBus->async_method_call(
2819 [asyncResp, resetType](const boost::system::error_code ec) {
2820 if (ec)
2821 {
2822 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2823 if (ec.value() == boost::asio::error::invalid_argument)
2824 {
2825 messages::actionParameterNotSupported(
2826 asyncResp->res, resetType, "Reset");
2827 }
2828 else
2829 {
2830 messages::internalError(asyncResp->res);
2831 }
2832 return;
2833 }
2834 messages::success(asyncResp->res);
2835 },
2836 "xyz.openbmc_project.State.Chassis",
2837 "/xyz/openbmc_project/state/chassis0",
2838 "org.freedesktop.DBus.Properties", "Set",
2839 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2840 dbus::utility::DbusVariantType{command});
2841 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002842 });
2843}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002844
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002845void handleComputerSystemCollectionHead(
2846 App& app, const crow::Request& req,
2847 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2848{
2849 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2850 {
2851 return;
2852 }
2853
2854 asyncResp->res.addHeader(
2855 boost::beast::http::field::link,
2856 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2857}
2858
Ed Tanouscc340dd2018-08-29 13:43:38 -07002859/**
Ed Tanous66173382018-08-15 18:20:59 -07002860 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002861 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002862inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002863{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002864
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002865 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2866 .privileges(redfish::privileges::headComputerSystem)
2867 .methods(boost::beast::http::verb::head)(
2868 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07002869 /**
2870 * Functions triggers appropriate requests on DBus
2871 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002872 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002873 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002874 .methods(boost::beast::http::verb::get)(
2875 [&app](const crow::Request& req,
2876 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002877 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002878 {
2879 return;
2880 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002881 asyncResp->res.addHeader(
2882 boost::beast::http::field::link,
2883 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002884 asyncResp->res.jsonValue["@odata.type"] =
2885 "#ComputerSystem.v1_16_0.ComputerSystem";
2886 asyncResp->res.jsonValue["Name"] = "system";
2887 asyncResp->res.jsonValue["Id"] = "system";
2888 asyncResp->res.jsonValue["SystemType"] = "Physical";
2889 asyncResp->res.jsonValue["Description"] = "Computer System";
2890 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2891 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2892 "Disabled";
2893 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2894 uint64_t(0);
2895 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2896 "Disabled";
2897 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002898
Ed Tanous002d39b2022-05-31 08:59:27 -07002899 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
2900 "/redfish/v1/Systems/system/Processors";
2901 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
2902 "/redfish/v1/Systems/system/Memory";
2903 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
2904 "/redfish/v1/Systems/system/Storage";
Ed Tanous029573d2019-02-01 10:57:49 -08002905
Ed Tanous002d39b2022-05-31 08:59:27 -07002906 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
2907 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
2908 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
2909 ["@Redfish.ActionInfo"] =
2910 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002911
Ed Tanous002d39b2022-05-31 08:59:27 -07002912 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
2913 "/redfish/v1/Systems/system/LogServices";
2914 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
2915 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002916
Ed Tanous002d39b2022-05-31 08:59:27 -07002917 nlohmann::json::array_t managedBy;
2918 nlohmann::json& manager = managedBy.emplace_back();
2919 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
2920 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
2921 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
2922 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002923
Ed Tanous002d39b2022-05-31 08:59:27 -07002924 // Fill in SerialConsole info
2925 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
2926 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
2927 true;
Ed Tanous14766872022-03-15 10:44:42 -07002928
Ed Tanous002d39b2022-05-31 08:59:27 -07002929 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2930 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
2931 true;
2932 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
2933 asyncResp->res
2934 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
2935 "Press ~. to exit console";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002936
2937#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002938 // Fill in GraphicalConsole info
2939 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
2940 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
2941 4;
2942 asyncResp->res
2943 .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"};
Ed Tanous14766872022-03-15 10:44:42 -07002944
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002945#endif // BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002946 constexpr const std::array<const char*, 4> inventoryForSystems = {
2947 "xyz.openbmc_project.Inventory.Item.Dimm",
2948 "xyz.openbmc_project.Inventory.Item.Cpu",
2949 "xyz.openbmc_project.Inventory.Item.Drive",
2950 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002951
Ed Tanous002d39b2022-05-31 08:59:27 -07002952 auto health = std::make_shared<HealthPopulate>(asyncResp);
2953 crow::connections::systemBus->async_method_call(
2954 [health](const boost::system::error_code ec,
2955 const std::vector<std::string>& resp) {
2956 if (ec)
2957 {
2958 // no inventory
2959 return;
2960 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002961
Ed Tanous002d39b2022-05-31 08:59:27 -07002962 health->inventory = resp;
2963 },
2964 "xyz.openbmc_project.ObjectMapper",
2965 "/xyz/openbmc_project/object_mapper",
2966 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2967 int32_t(0), inventoryForSystems);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002968
Ed Tanous002d39b2022-05-31 08:59:27 -07002969 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002970
Ed Tanous002d39b2022-05-31 08:59:27 -07002971 getMainChassisId(asyncResp,
2972 [](const std::string& chassisId,
2973 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2974 nlohmann::json::array_t chassisArray;
2975 nlohmann::json& chassis = chassisArray.emplace_back();
2976 chassis["@odata.id"] = "/redfish/v1/Chassis/" + chassisId;
2977 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
2978 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002979
Ed Tanous002d39b2022-05-31 08:59:27 -07002980 getLocationIndicatorActive(asyncResp);
2981 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2982 getIndicatorLedState(asyncResp);
2983 getComputerSystem(asyncResp, health);
2984 getHostState(asyncResp);
2985 getBootProperties(asyncResp);
2986 getBootProgress(asyncResp);
2987 getPCIeDeviceList(asyncResp, "PCIeDevices");
2988 getHostWatchdogTimer(asyncResp);
2989 getPowerRestorePolicy(asyncResp);
2990 getAutomaticRetry(asyncResp);
2991 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002992#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07002993 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002994#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07002995 getTrustedModuleRequiredToBoot(asyncResp);
2996 getPowerMode(asyncResp);
2997 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002998 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002999
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003000 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003001 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003002 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003003 [&app](const crow::Request& req,
3004 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003005 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003006 {
3007 return;
3008 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003009 asyncResp->res.addHeader(
3010 boost::beast::http::field::link,
3011 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3012
Ed Tanous002d39b2022-05-31 08:59:27 -07003013 std::optional<bool> locationIndicatorActive;
3014 std::optional<std::string> indicatorLed;
3015 std::optional<std::string> assetTag;
3016 std::optional<std::string> powerRestorePolicy;
3017 std::optional<std::string> powerMode;
3018 std::optional<bool> wdtEnable;
3019 std::optional<std::string> wdtTimeOutAction;
3020 std::optional<std::string> bootSource;
3021 std::optional<std::string> bootType;
3022 std::optional<std::string> bootEnable;
3023 std::optional<std::string> bootAutomaticRetry;
3024 std::optional<bool> bootTrustedModuleRequired;
3025 std::optional<bool> ipsEnable;
3026 std::optional<uint8_t> ipsEnterUtil;
3027 std::optional<uint64_t> ipsEnterTime;
3028 std::optional<uint8_t> ipsExitUtil;
3029 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003030
Ed Tanous002d39b2022-05-31 08:59:27 -07003031 // clang-format off
Jiaqing Zhaoaa6d4532022-06-02 17:47:58 +08003032 if (!json_util::readJsonPatch(
3033 req, asyncResp->res,
3034 "IndicatorLED", indicatorLed,
3035 "LocationIndicatorActive", locationIndicatorActive,
3036 "AssetTag", assetTag,
3037 "PowerRestorePolicy", powerRestorePolicy,
3038 "PowerMode", powerMode,
3039 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3040 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3041 "Boot/BootSourceOverrideTarget", bootSource,
3042 "Boot/BootSourceOverrideMode", bootType,
3043 "Boot/BootSourceOverrideEnabled", bootEnable,
3044 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
3045 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3046 "IdlePowerSaver/Enabled", ipsEnable,
3047 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3048 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3049 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3050 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3051 {
3052 return;
3053 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003054 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003055
Ed Tanous002d39b2022-05-31 08:59:27 -07003056 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003057
Ed Tanous002d39b2022-05-31 08:59:27 -07003058 if (assetTag)
3059 {
3060 setAssetTag(asyncResp, *assetTag);
3061 }
James Feistb49ac872019-05-21 15:12:01 -07003062
Ed Tanous002d39b2022-05-31 08:59:27 -07003063 if (wdtEnable || wdtTimeOutAction)
3064 {
3065 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3066 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003067
Ed Tanous002d39b2022-05-31 08:59:27 -07003068 if (bootSource || bootType || bootEnable)
3069 {
3070 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3071 }
3072 if (bootAutomaticRetry)
3073 {
3074 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3075 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003076
Ed Tanous002d39b2022-05-31 08:59:27 -07003077 if (bootTrustedModuleRequired)
3078 {
3079 setTrustedModuleRequiredToBoot(asyncResp,
3080 *bootTrustedModuleRequired);
3081 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003082
Ed Tanous002d39b2022-05-31 08:59:27 -07003083 if (locationIndicatorActive)
3084 {
3085 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3086 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003087
Ed Tanous002d39b2022-05-31 08:59:27 -07003088 // TODO (Gunnar): Remove IndicatorLED after enough time has
3089 // passed
3090 if (indicatorLed)
3091 {
3092 setIndicatorLedState(asyncResp, *indicatorLed);
3093 asyncResp->res.addHeader(boost::beast::http::field::warning,
3094 "299 - \"IndicatorLED is deprecated. Use "
3095 "LocationIndicatorActive instead.\"");
3096 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003097
Ed Tanous002d39b2022-05-31 08:59:27 -07003098 if (powerRestorePolicy)
3099 {
3100 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3101 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003102
Ed Tanous002d39b2022-05-31 08:59:27 -07003103 if (powerMode)
3104 {
3105 setPowerMode(asyncResp, *powerMode);
3106 }
Chris Cain37bbf982021-09-20 10:53:09 -05003107
Ed Tanous002d39b2022-05-31 08:59:27 -07003108 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3109 ipsExitTime)
3110 {
3111 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3112 ipsExitUtil, ipsExitTime);
3113 }
3114 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003115}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303116
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003117void handleSystemCollectionResetActionHead(
3118 crow::App& app, const crow::Request& req,
3119 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3120{
3121 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3122 {
3123 return;
3124 }
3125 asyncResp->res.addHeader(
3126 boost::beast::http::field::link,
3127 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3128}
3129
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303130/**
3131 * SystemResetActionInfo derived class for delivering Computer Systems
3132 * ResetType AllowableValues using ResetInfo schema.
3133 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003134inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303135{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003136 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3137 .privileges(redfish::privileges::headActionInfo)
3138 .methods(boost::beast::http::verb::head)(std::bind_front(
3139 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303140 /**
3141 * Functions triggers appropriate requests on DBus
3142 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003143 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003144 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003145 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003146 [&app](const crow::Request& req,
3147 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003148 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003149 {
3150 return;
3151 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003152 asyncResp->res.addHeader(
3153 boost::beast::http::field::link,
3154 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003155
Ed Tanous002d39b2022-05-31 08:59:27 -07003156 asyncResp->res.jsonValue["@odata.id"] =
3157 "/redfish/v1/Systems/system/ResetActionInfo";
3158 asyncResp->res.jsonValue["@odata.type"] =
3159 "#ActionInfo.v1_1_2.ActionInfo";
3160 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3161 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003162
3163 nlohmann::json::array_t parameters;
3164 nlohmann::json::object_t parameter;
3165
3166 parameter["Name"] = "ResetType";
3167 parameter["Required"] = true;
3168 parameter["DataType"] = "String";
3169 nlohmann::json::array_t allowableValues;
3170 allowableValues.emplace_back("On");
3171 allowableValues.emplace_back("ForceOff");
3172 allowableValues.emplace_back("ForceOn");
3173 allowableValues.emplace_back("ForceRestart");
3174 allowableValues.emplace_back("GracefulRestart");
3175 allowableValues.emplace_back("GracefulShutdown");
3176 allowableValues.emplace_back("PowerCycle");
3177 allowableValues.emplace_back("Nmi");
3178 parameter["AllowableValues"] = std::move(allowableValues);
3179 parameters.emplace_back(std::move(parameter));
3180
3181 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003182 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003183}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003184} // namespace redfish