blob: 0c2c53c192d9dada4b287b5a7b48903f061631df [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>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020031#include <utils/json_utils.hpp>
Willy Tueee00132022-06-14 14:53:17 -070032#include <utils/sw_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050033
Ed Tanousabf2add2019-01-22 16:40:12 -080034#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020035
Ed Tanous1abe55e2018-09-05 08:30:59 -070036namespace redfish
37{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020038
Alpana Kumari9d3ae102019-04-12 06:49:32 -050039/**
40 * @brief Updates the Functional State of DIMMs
41 *
42 * @param[in] aResp Shared pointer for completing asynchronous calls
43 * @param[in] dimmState Dimm's Functional state, true/false
44 *
45 * @return None.
46 */
zhanghch058d1b46d2021-04-01 11:18:24 +080047inline void
48 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070049 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070051 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052
Gunnar Mills4e0453b2020-07-08 14:00:30 -050053 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050054 // Update STATE only if previous State was DISABLED and current Dimm is
55 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070056 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050057 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
58 if (prevMemSummary == "Disabled")
59 {
Ed Tanouse05aec52022-01-25 10:28:56 -080060 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050061 {
62 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
63 "Enabled";
64 }
65 }
66}
67
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050068/*
69 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
70 *
71 * @param[in] aResp Shared pointer for completing asynchronous calls
72 * @param[in] cpuPresenceState CPU present or not
73 *
74 * @return None.
75 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070076inline void
77 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
78 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070080 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081
Ed Tanous55f79e62022-01-25 11:26:16 -080082 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050083 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050084 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080085 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080086 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050087 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080088 if (procCountPtr != nullptr)
89 {
90 // shouldn't be possible to be nullptr
91 *procCountPtr += 1;
92 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050094}
95
96/*
97 * @brief Update "ProcessorSummary" "Status" "State" based on
98 * CPU Functional State
99 *
100 * @param[in] aResp Shared pointer for completing asynchronous calls
101 * @param[in] cpuFunctionalState is CPU functional true/false
102 *
103 * @return None.
104 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700105inline void
106 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
107 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700109 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110
Ed Tanous02cad962022-06-30 16:50:15 -0700111 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500112 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
113
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500114 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500115 // Update STATE only if previous State was Non_Functional and current CPU is
116 // Functional.
117 if (prevProcState == "Disabled")
118 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800119 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500120 {
121 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
122 "Enabled";
123 }
124 }
125}
126
Ed Tanousb9d36b42022-02-26 21:42:46 -0800127inline void
128 getProcessorProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
129 const std::string& service, const std::string& path,
130 const dbus::utility::DBusPropertiesMap& properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500131{
132
133 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
134
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700135 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
136 const bool cpuPresenceCheck) {
137 if (ec3)
138 {
139 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
140 return;
141 }
142 modifyCpuPresenceState(aResp, cpuPresenceCheck);
143 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500144
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700145 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
146 const bool cpuFunctionalCheck) {
147 if (ec3)
148 {
149 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
150 return;
151 }
152 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
153 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500154
155 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700156 sdbusplus::asio::getProperty<bool>(
157 *crow::connections::systemBus, service, path,
158 "xyz.openbmc_project.Inventory.Item", "Present",
159 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500160
161 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700162 sdbusplus::asio::getProperty<bool>(
163 *crow::connections::systemBus, service, path,
164 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
165 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500166
167 for (const auto& property : properties)
168 {
169
170 // TODO: Get Model
171
172 // Get CoreCount
173 if (property.first == "CoreCount")
174 {
175
176 // Get CPU CoreCount and add it to the total
177 const uint16_t* coreCountVal =
178 std::get_if<uint16_t>(&property.second);
179
Ed Tanouse662eae2022-01-25 10:39:19 -0800180 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500181 {
182 messages::internalError(aResp->res);
183 return;
184 }
185
186 nlohmann::json& coreCount =
187 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
188 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
189
190 if (coreCountPtr == nullptr)
191 {
Krzysztof Grobelnya6669022022-08-10 10:11:11 +0200192 coreCount = *coreCountVal;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500193 }
194 else
195 {
196 *coreCountPtr += *coreCountVal;
197 }
198 }
199 }
200}
201
202/*
203 * @brief Get ProcessorSummary fields
204 *
205 * @param[in] aResp Shared pointer for completing asynchronous calls
206 * @param[in] service dbus service for Cpu Information
207 * @param[in] path dbus path for Cpu
208 *
209 * @return None.
210 */
211inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
212 const std::string& service,
213 const std::string& path)
214{
215
216 crow::connections::systemBus->async_method_call(
217 [aResp, service,
218 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800219 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700220 if (ec2)
221 {
222 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
223 messages::internalError(aResp->res);
224 return;
225 }
226 getProcessorProperties(aResp, service, path, properties);
Ali Ahmed03fbed92021-09-03 02:33:43 -0500227 },
228 service, path, "org.freedesktop.DBus.Properties", "GetAll",
229 "xyz.openbmc_project.Inventory.Item.Cpu");
230}
231
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500232/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700233 * @brief Retrieves computer system properties over dbus
234 *
235 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500236 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700237 *
238 * @return None.
239 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700240inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800241 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700242 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700243{
Ed Tanous6c34de42018-08-29 13:37:36 -0700244 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500245
Ed Tanous6c34de42018-08-29 13:37:36 -0700246 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800247 [aResp,
248 systemHealth](const boost::system::error_code ec,
249 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700250 if (ec)
251 {
252 BMCWEB_LOG_DEBUG << "DBUS response error";
253 messages::internalError(aResp->res);
254 return;
255 }
256 // Iterate over all retrieved ObjectPaths.
257 for (const std::pair<
258 std::string,
259 std::vector<std::pair<std::string, std::vector<std::string>>>>&
260 object : subtree)
261 {
262 const std::string& path = object.first;
263 BMCWEB_LOG_DEBUG << "Got path: " << path;
264 const std::vector<std::pair<std::string, std::vector<std::string>>>&
265 connectionNames = object.second;
266 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700267 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700268 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700269 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700270
271 auto memoryHealth = std::make_shared<HealthPopulate>(
272 aResp, "/MemorySummary/Status"_json_pointer);
273
274 auto cpuHealth = std::make_shared<HealthPopulate>(
275 aResp, "/ProcessorSummary/Status"_json_pointer);
276
277 systemHealth->children.emplace_back(memoryHealth);
278 systemHealth->children.emplace_back(cpuHealth);
279
280 // This is not system, so check if it's cpu, dimm, UUID or
281 // BiosVer
282 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700283 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700284 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700285 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700286 if (interfaceName ==
287 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700288 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700289 BMCWEB_LOG_DEBUG
290 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500291
Ed Tanous002d39b2022-05-31 08:59:27 -0700292 crow::connections::systemBus->async_method_call(
293 [aResp, service{connection.first},
294 path](const boost::system::error_code ec2,
295 const dbus::utility::DBusPropertiesMap&
296 properties) {
297 if (ec2)
298 {
299 BMCWEB_LOG_ERROR << "DBUS response error "
300 << ec2;
301 messages::internalError(aResp->res);
302 return;
303 }
304 BMCWEB_LOG_DEBUG << "Got " << properties.size()
305 << " Dimm properties.";
306
307 if (!properties.empty())
308 {
309 for (const std::pair<
310 std::string,
311 dbus::utility::DbusVariantType>&
312 property : properties)
313 {
314 if (property.first != "MemorySizeInKB")
Ed Tanous029573d2019-02-01 10:57:49 -0800315 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700316 continue;
Ed Tanous029573d2019-02-01 10:57:49 -0800317 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700318 const uint32_t* value =
319 std::get_if<uint32_t>(&property.second);
320 if (value == nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800321 {
322 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -0700323 << "Find incorrect type of MemorySize";
324 continue;
325 }
326 nlohmann::json& totalMemory =
327 aResp->res
328 .jsonValue["MemorySummary"]
329 ["TotalSystemMemoryGiB"];
Ed Tanous02cad962022-06-30 16:50:15 -0700330 const uint64_t* preValue =
331 totalMemory.get_ptr<const uint64_t*>();
Ed Tanous002d39b2022-05-31 08:59:27 -0700332 if (preValue == nullptr)
333 {
334 continue;
335 }
336 aResp->res
337 .jsonValue["MemorySummary"]
338 ["TotalSystemMemoryGiB"] =
339 *value / (1024 * 1024) + *preValue;
340 aResp->res.jsonValue["MemorySummary"]
341 ["Status"]["State"] =
342 "Enabled";
343 }
344 }
345 else
346 {
347 sdbusplus::asio::getProperty<bool>(
348 *crow::connections::systemBus, service,
349 path,
350 "xyz.openbmc_project.State."
351 "Decorator.OperationalStatus",
352 "Functional",
353 [aResp](const boost::system::error_code ec3,
354 bool dimmState) {
355 if (ec3)
356 {
357 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000358 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800359 return;
360 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700361 updateDimmProperties(aResp, dimmState);
362 });
363 }
364 },
365 connection.first, path,
366 "org.freedesktop.DBus.Properties", "GetAll",
367 "xyz.openbmc_project.Inventory.Item.Dimm");
368
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.";
385 crow::connections::systemBus->async_method_call(
386 [aResp](const boost::system::error_code ec3,
387 const dbus::utility::DBusPropertiesMap&
388 properties) {
389 if (ec3)
390 {
391 BMCWEB_LOG_DEBUG << "DBUS response error "
392 << ec3;
393 messages::internalError(aResp->res);
394 return;
395 }
396 BMCWEB_LOG_DEBUG << "Got " << properties.size()
397 << " UUID properties.";
398 for (const std::pair<
399 std::string,
400 dbus::utility::DbusVariantType>& property :
401 properties)
402 {
403 if (property.first == "UUID")
404 {
405 const std::string* value =
406 std::get_if<std::string>(
407 &property.second);
408
409 if (value != nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800410 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700411 std::string valueStr = *value;
412 if (valueStr.size() == 32)
Ed Tanous029573d2019-02-01 10:57:49 -0800413 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700414 valueStr.insert(8, 1, '-');
415 valueStr.insert(13, 1, '-');
416 valueStr.insert(18, 1, '-');
417 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700418 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700419 BMCWEB_LOG_DEBUG << "UUID = "
420 << valueStr;
421 aResp->res.jsonValue["UUID"] = valueStr;
Ed Tanous029573d2019-02-01 10:57:49 -0800422 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700423 }
424 }
425 },
426 connection.first, path,
427 "org.freedesktop.DBus.Properties", "GetAll",
428 "xyz.openbmc_project.Common.UUID");
429 }
430 else if (interfaceName ==
431 "xyz.openbmc_project.Inventory.Item.System")
432 {
433 crow::connections::systemBus->async_method_call(
434 [aResp](const boost::system::error_code ec2,
435 const dbus::utility::DBusPropertiesMap&
436 propertiesList) {
437 if (ec2)
438 {
439 // doesn't have to include this
440 // interface
441 return;
442 }
443 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
444 << " properties for system";
445 for (const std::pair<
446 std::string,
447 dbus::utility::DbusVariantType>& property :
448 propertiesList)
449 {
450 const std::string& propertyName =
451 property.first;
452 if ((propertyName == "PartNumber") ||
453 (propertyName == "SerialNumber") ||
454 (propertyName == "Manufacturer") ||
455 (propertyName == "Model") ||
456 (propertyName == "SubModel"))
457 {
458 const std::string* value =
459 std::get_if<std::string>(
460 &property.second);
461 if (value != nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800462 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700463 aResp->res.jsonValue[propertyName] =
464 *value;
Ed Tanous029573d2019-02-01 10:57:49 -0800465 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700466 }
467 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500468
Ed Tanous002d39b2022-05-31 08:59:27 -0700469 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700470 sw_util::populateSoftwareInformation(
471 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700472 false);
473 },
474 connection.first, path,
475 "org.freedesktop.DBus.Properties", "GetAll",
476 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700477
Ed Tanous002d39b2022-05-31 08:59:27 -0700478 sdbusplus::asio::getProperty<std::string>(
479 *crow::connections::systemBus, connection.first,
480 path,
481 "xyz.openbmc_project.Inventory.Decorator."
482 "AssetTag",
483 "AssetTag",
484 [aResp](const boost::system::error_code ec2,
485 const std::string& value) {
486 if (ec2)
487 {
488 // doesn't have to include this
489 // interface
490 return;
491 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700492
Ed Tanous002d39b2022-05-31 08:59:27 -0700493 aResp->res.jsonValue["AssetTag"] = value;
494 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700495 }
496 }
497 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700498 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700499 },
500 "xyz.openbmc_project.ObjectMapper",
501 "/xyz/openbmc_project/object_mapper",
502 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700503 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500504 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700505 "xyz.openbmc_project.Inventory.Decorator.Asset",
506 "xyz.openbmc_project.Inventory.Item.Cpu",
507 "xyz.openbmc_project.Inventory.Item.Dimm",
508 "xyz.openbmc_project.Inventory.Item.System",
509 "xyz.openbmc_project.Common.UUID",
510 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700511}
512
513/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700514 * @brief Retrieves host state properties over dbus
515 *
516 * @param[in] aResp Shared pointer for completing asynchronous calls.
517 *
518 * @return None.
519 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800520inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700521{
522 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700523 sdbusplus::asio::getProperty<std::string>(
524 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
525 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
526 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800527 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700528 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700529 if (ec)
530 {
531 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700532 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700533 // Service not available, no error, just don't return
534 // host state info
535 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700536 return;
537 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700538 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
539 messages::internalError(aResp->res);
540 return;
541 }
Ed Tanous66173382018-08-15 18:20:59 -0700542
Ed Tanous002d39b2022-05-31 08:59:27 -0700543 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
544 // Verify Host State
545 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
546 {
547 aResp->res.jsonValue["PowerState"] = "On";
548 aResp->res.jsonValue["Status"]["State"] = "Enabled";
549 }
550 else if (hostState ==
551 "xyz.openbmc_project.State.Host.HostState.Quiesced")
552 {
553 aResp->res.jsonValue["PowerState"] = "On";
554 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
555 }
556 else if (hostState ==
557 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
558 {
559 aResp->res.jsonValue["PowerState"] = "On";
560 aResp->res.jsonValue["Status"]["State"] = "InTest";
561 }
562 else if (
563 hostState ==
564 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
565 {
566 aResp->res.jsonValue["PowerState"] = "PoweringOn";
567 aResp->res.jsonValue["Status"]["State"] = "Starting";
568 }
569 else if (hostState ==
570 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
571 {
572 aResp->res.jsonValue["PowerState"] = "PoweringOff";
573 aResp->res.jsonValue["Status"]["State"] = "Disabled";
574 }
575 else
576 {
577 aResp->res.jsonValue["PowerState"] = "Off";
578 aResp->res.jsonValue["Status"]["State"] = "Disabled";
579 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700580 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700581}
582
583/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500584 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530585 *
586 * @param[in] dbusSource The boot source in DBUS speak.
587 *
588 * @return Returns as a string, the boot source in Redfish terms. If translation
589 * cannot be done, returns an empty string.
590 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000591inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530592{
593 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
594 {
595 return "None";
596 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700597 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530598 {
599 return "Hdd";
600 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700601 if (dbusSource ==
602 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530603 {
604 return "Cd";
605 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700606 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530607 {
608 return "Pxe";
609 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700610 if (dbusSource ==
611 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700612 {
613 return "Usb";
614 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700615 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530616}
617
618/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300619 * @brief Translates boot type DBUS property value to redfish.
620 *
621 * @param[in] dbusType The boot type in DBUS speak.
622 *
623 * @return Returns as a string, the boot type in Redfish terms. If translation
624 * cannot be done, returns an empty string.
625 */
626inline std::string dbusToRfBootType(const std::string& dbusType)
627{
628 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
629 {
630 return "Legacy";
631 }
632 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
633 {
634 return "UEFI";
635 }
636 return "";
637}
638
639/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500640 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530641 *
642 * @param[in] dbusMode The boot mode in DBUS speak.
643 *
644 * @return Returns as a string, the boot mode in Redfish terms. If translation
645 * cannot be done, returns an empty string.
646 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000647inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530648{
649 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
650 {
651 return "None";
652 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700653 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530654 {
655 return "Diags";
656 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700657 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530658 {
659 return "BiosSetup";
660 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700661 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530662}
663
664/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600665 * @brief Translates boot progress DBUS property value to redfish.
666 *
667 * @param[in] dbusBootProgress The boot progress in DBUS speak.
668 *
669 * @return Returns as a string, the boot progress in Redfish terms. If
670 * translation cannot be done, returns "None".
671 */
672inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
673{
674 // Now convert the D-Bus BootProgress to the appropriate Redfish
675 // enum
676 std::string rfBpLastState = "None";
677 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
678 "ProgressStages.Unspecified")
679 {
680 rfBpLastState = "None";
681 }
682 else if (dbusBootProgress ==
683 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
684 "PrimaryProcInit")
685 {
686 rfBpLastState = "PrimaryProcessorInitializationStarted";
687 }
688 else if (dbusBootProgress ==
689 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
690 "BusInit")
691 {
692 rfBpLastState = "BusInitializationStarted";
693 }
694 else if (dbusBootProgress ==
695 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
696 "MemoryInit")
697 {
698 rfBpLastState = "MemoryInitializationStarted";
699 }
700 else if (dbusBootProgress ==
701 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
702 "SecondaryProcInit")
703 {
704 rfBpLastState = "SecondaryProcessorInitializationStarted";
705 }
706 else if (dbusBootProgress ==
707 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
708 "PCIInit")
709 {
710 rfBpLastState = "PCIResourceConfigStarted";
711 }
712 else if (dbusBootProgress ==
713 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
714 "SystemSetup")
715 {
716 rfBpLastState = "SetupEntered";
717 }
718 else if (dbusBootProgress ==
719 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
720 "SystemInitComplete")
721 {
722 rfBpLastState = "SystemHardwareInitializationComplete";
723 }
724 else if (dbusBootProgress ==
725 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
726 "OSStart")
727 {
728 rfBpLastState = "OSBootStarted";
729 }
730 else if (dbusBootProgress ==
731 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
732 "OSRunning")
733 {
734 rfBpLastState = "OSRunning";
735 }
736 else
737 {
738 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
739 << dbusBootProgress;
740 // Just return the default
741 }
742 return rfBpLastState;
743}
744
745/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500746 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530747 *
748 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700749 * @param[out] bootSource The DBus source
750 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530751 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700752 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530753 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800754inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500755 const std::string& rfSource,
756 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530757{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300758 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
759 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700760
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530761 if (rfSource == "None")
762 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700763 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530764 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700765 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530766 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700767 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
768 }
769 else if (rfSource == "Hdd")
770 {
771 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
772 }
773 else if (rfSource == "Diags")
774 {
775 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
776 }
777 else if (rfSource == "Cd")
778 {
779 bootSource =
780 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
781 }
782 else if (rfSource == "BiosSetup")
783 {
784 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530785 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700786 else if (rfSource == "Usb")
787 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700788 bootSource =
789 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700790 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 else
792 {
George Liu0fda0f12021-11-16 10:06:17 +0800793 BMCWEB_LOG_DEBUG
794 << "Invalid property value for BootSourceOverrideTarget: "
795 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700796 messages::propertyValueNotInList(aResp->res, rfSource,
797 "BootSourceTargetOverride");
798 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530799 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700800 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530801}
Ali Ahmed19817712021-06-29 17:01:52 -0500802
Andrew Geissler978b8802020-11-19 13:36:40 -0600803/**
804 * @brief Retrieves boot progress of the system
805 *
806 * @param[in] aResp Shared pointer for generating response message.
807 *
808 * @return None.
809 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800810inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600811{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700812 sdbusplus::asio::getProperty<std::string>(
813 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
814 "/xyz/openbmc_project/state/host0",
815 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600816 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700817 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700818 if (ec)
819 {
820 // BootProgress is an optional object so just do nothing if
821 // not found
822 return;
823 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600824
Ed Tanous002d39b2022-05-31 08:59:27 -0700825 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600826
Ed Tanous002d39b2022-05-31 08:59:27 -0700827 aResp->res.jsonValue["BootProgress"]["LastState"] =
828 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700829 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600830}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530831
832/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300833 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300834 *
835 * @param[in] aResp Shared pointer for generating response message.
836 *
837 * @return None.
838 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300839
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300840inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300841{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700842 sdbusplus::asio::getProperty<std::string>(
843 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
844 "/xyz/openbmc_project/control/host0/boot",
845 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300846 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700847 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700848 if (ec)
849 {
850 // not an error, don't have to have the interface
851 return;
852 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300853
Ed Tanous002d39b2022-05-31 08:59:27 -0700854 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300855
Ed Tanous002d39b2022-05-31 08:59:27 -0700856 aResp->res.jsonValue["Boot"]
857 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
858 {"Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300859
Ed Tanous002d39b2022-05-31 08:59:27 -0700860 auto rfType = dbusToRfBootType(bootType);
861 if (rfType.empty())
862 {
863 messages::internalError(aResp->res);
864 return;
865 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866
Ed Tanous002d39b2022-05-31 08:59:27 -0700867 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700868 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300869}
870
871/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300872 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530873 *
874 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530875 *
876 * @return None.
877 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300878
879inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530880{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700881 sdbusplus::asio::getProperty<std::string>(
882 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
883 "/xyz/openbmc_project/control/host0/boot",
884 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300885 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700886 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700887 if (ec)
888 {
889 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
890 messages::internalError(aResp->res);
891 return;
892 }
893
894 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
895
896 aResp->res
897 .jsonValue["Boot"]
898 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
899 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
900
901 if (bootModeStr !=
902 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
903 {
904 auto rfMode = dbusToRfBootMode(bootModeStr);
905 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530906 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700907 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
908 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530909 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700910 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700911 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530912}
913
914/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300915 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530916 *
917 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530918 *
919 * @return None.
920 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300921
922inline void
923 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530924{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700925 sdbusplus::asio::getProperty<std::string>(
926 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
927 "/xyz/openbmc_project/control/host0/boot",
928 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300929 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700930 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700931 if (ec)
932 {
933 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000934 if (ec.value() == boost::asio::error::host_unreachable)
935 {
936 return;
937 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700938 messages::internalError(aResp->res);
939 return;
940 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530941
Ed Tanous002d39b2022-05-31 08:59:27 -0700942 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530943
Ed Tanous002d39b2022-05-31 08:59:27 -0700944 auto rfSource = dbusToRfBootSource(bootSourceStr);
945 if (!rfSource.empty())
946 {
947 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
948 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300949
Ed Tanous002d39b2022-05-31 08:59:27 -0700950 // Get BootMode as BootSourceOverrideTarget is constructed
951 // from both BootSource and BootMode
952 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700953 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530954}
955
956/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300957 * @brief This functions abstracts all the logic behind getting a
958 * "BootSourceOverrideEnabled" property from an overall boot override enable
959 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530960 *
961 * @param[in] aResp Shared pointer for generating response message.
962 *
963 * @return None.
964 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530965
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300966inline void
967 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
968 const bool bootOverrideEnableSetting)
969{
970 if (!bootOverrideEnableSetting)
971 {
972 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
973 return;
974 }
975
976 // If boot source override is enabled, we need to check 'one_time'
977 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700978 sdbusplus::asio::getProperty<bool>(
979 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
980 "/xyz/openbmc_project/control/host0/boot/one_time",
981 "xyz.openbmc_project.Object.Enable", "Enabled",
982 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700983 if (ec)
984 {
985 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
986 messages::internalError(aResp->res);
987 return;
988 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530989
Ed Tanous002d39b2022-05-31 08:59:27 -0700990 if (oneTimeSetting)
991 {
992 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
993 }
994 else
995 {
996 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
997 "Continuous";
998 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700999 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000}
1001
1002/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001003 * @brief Retrieves boot override enable over DBUS
1004 *
1005 * @param[in] aResp Shared pointer for generating response message.
1006 *
1007 * @return None.
1008 */
1009
1010inline void
1011 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1012{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001013 sdbusplus::asio::getProperty<bool>(
1014 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1015 "/xyz/openbmc_project/control/host0/boot",
1016 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001017 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001018 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001019 if (ec)
1020 {
1021 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001022 if (ec.value() == boost::asio::error::host_unreachable)
1023 {
1024 return;
1025 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001026 messages::internalError(aResp->res);
1027 return;
1028 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029
Ed Tanous002d39b2022-05-31 08:59:27 -07001030 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001031 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001032}
1033
1034/**
1035 * @brief Retrieves boot source override properties
1036 *
1037 * @param[in] aResp Shared pointer for generating response message.
1038 *
1039 * @return None.
1040 */
1041inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1042{
1043 BMCWEB_LOG_DEBUG << "Get boot information.";
1044
1045 getBootOverrideSource(aResp);
1046 getBootOverrideType(aResp);
1047 getBootOverrideEnable(aResp);
1048}
1049
1050/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001051 * @brief Retrieves the Last Reset Time
1052 *
1053 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1054 * and power off. Even though this is the "system" Redfish object look at the
1055 * chassis D-Bus interface for the LastStateChangeTime since this has the
1056 * last power operation time.
1057 *
1058 * @param[in] aResp Shared pointer for generating response message.
1059 *
1060 * @return None.
1061 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001062inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001063{
1064 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1065
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001066 sdbusplus::asio::getProperty<uint64_t>(
1067 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1068 "/xyz/openbmc_project/state/chassis0",
1069 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1070 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001071 if (ec)
1072 {
1073 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1074 return;
1075 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001076
Ed Tanous002d39b2022-05-31 08:59:27 -07001077 // LastStateChangeTime is epoch time, in milliseconds
1078 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1079 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001080
Ed Tanous002d39b2022-05-31 08:59:27 -07001081 // Convert to ISO 8601 standard
1082 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001083 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001084 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001085}
1086
1087/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001088 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1089 *
1090 * @param[in] aResp Shared pointer for generating response message.
1091 *
1092 * @return None.
1093 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001094inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001095{
1096 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1097
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001098 sdbusplus::asio::getProperty<bool>(
1099 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1100 "/xyz/openbmc_project/control/host0/auto_reboot",
1101 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1102 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001103 if (ec)
1104 {
1105 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1106 return;
1107 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001108
Ed Tanous002d39b2022-05-31 08:59:27 -07001109 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1110 if (autoRebootEnabled)
1111 {
1112 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1113 "RetryAttempts";
1114 // If AutomaticRetry (AutoReboot) is enabled see how many
1115 // attempts are left
1116 sdbusplus::asio::getProperty<uint32_t>(
1117 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1118 "/xyz/openbmc_project/state/host0",
1119 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1120 "AttemptsLeft",
1121 [aResp](const boost::system::error_code ec2,
1122 const uint32_t autoRebootAttemptsLeft) {
1123 if (ec2)
1124 {
1125 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1126 return;
1127 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001128
Ed Tanous002d39b2022-05-31 08:59:27 -07001129 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1130 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001131
Ed Tanous002d39b2022-05-31 08:59:27 -07001132 aResp->res
1133 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1134 autoRebootAttemptsLeft;
1135 });
1136 }
1137 else
1138 {
1139 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1140 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001141
Ed Tanous002d39b2022-05-31 08:59:27 -07001142 // Not on D-Bus. Hardcoded here:
1143 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1144 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001145
Ed Tanous002d39b2022-05-31 08:59:27 -07001146 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1147 // and RetryAttempts. OpenBMC only supports Disabled and
1148 // RetryAttempts.
1149 aResp->res.jsonValue["Boot"]
1150 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1151 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001152 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001153}
1154
1155/**
George Liuc6a620f2020-04-10 17:18:11 +08001156 * @brief Retrieves power restore policy over DBUS.
1157 *
1158 * @param[in] aResp Shared pointer for generating response message.
1159 *
1160 * @return None.
1161 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001162inline void
1163 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001164{
1165 BMCWEB_LOG_DEBUG << "Get power restore policy";
1166
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001167 sdbusplus::asio::getProperty<std::string>(
1168 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1169 "/xyz/openbmc_project/control/host0/power_restore_policy",
1170 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1171 [aResp](const boost::system::error_code ec, const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001172 if (ec)
1173 {
1174 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1175 return;
1176 }
George Liuc6a620f2020-04-10 17:18:11 +08001177
Ed Tanous002d39b2022-05-31 08:59:27 -07001178 const boost::container::flat_map<std::string, std::string> policyMaps = {
1179 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1180 "AlwaysOn"},
1181 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1182 "AlwaysOff"},
1183 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1184 "LastState"},
1185 // Return `AlwaysOff` when power restore policy set to "None"
1186 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1187 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001188
Ed Tanous002d39b2022-05-31 08:59:27 -07001189 auto policyMapsIt = policyMaps.find(policy);
1190 if (policyMapsIt == policyMaps.end())
1191 {
1192 messages::internalError(aResp->res);
1193 return;
1194 }
George Liuc6a620f2020-04-10 17:18:11 +08001195
Ed Tanous002d39b2022-05-31 08:59:27 -07001196 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001197 });
George Liuc6a620f2020-04-10 17:18:11 +08001198}
1199
1200/**
Ali Ahmed19817712021-06-29 17:01:52 -05001201 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1202 * TPM is required for booting the host.
1203 *
1204 * @param[in] aResp Shared pointer for generating response message.
1205 *
1206 * @return None.
1207 */
1208inline void getTrustedModuleRequiredToBoot(
1209 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1210{
1211 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1212
1213 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001214 [aResp](const boost::system::error_code ec,
1215 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001216 if (ec)
1217 {
1218 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1219 << ec;
1220 // This is an optional D-Bus object so just return if
1221 // error occurs
1222 return;
1223 }
1224 if (subtree.empty())
1225 {
1226 // As noted above, this is an optional interface so just return
1227 // if there is no instance found
1228 return;
1229 }
1230
1231 /* When there is more than one TPMEnable object... */
1232 if (subtree.size() > 1)
1233 {
1234 BMCWEB_LOG_DEBUG
1235 << "DBUS response has more than 1 TPM Enable object:"
1236 << subtree.size();
1237 // Throw an internal Error and return
1238 messages::internalError(aResp->res);
1239 return;
1240 }
1241
1242 // Make sure the Dbus response map has a service and objectPath
1243 // field
1244 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1245 {
1246 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1247 messages::internalError(aResp->res);
1248 return;
1249 }
1250
1251 const std::string& path = subtree[0].first;
1252 const std::string& serv = subtree[0].second.begin()->first;
1253
1254 // Valid TPM Enable object found, now reading the current value
1255 sdbusplus::asio::getProperty<bool>(
1256 *crow::connections::systemBus, serv, path,
1257 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous8a592812022-06-04 09:06:59 -07001258 [aResp](const boost::system::error_code ec2, bool tpmRequired) {
1259 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001260 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001261 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001262 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001263 messages::internalError(aResp->res);
1264 return;
1265 }
1266
Ed Tanous002d39b2022-05-31 08:59:27 -07001267 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001268 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001269 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1270 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001271 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001272 else
1273 {
1274 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1275 "Disabled";
1276 }
1277 });
Ali Ahmed19817712021-06-29 17:01:52 -05001278 },
1279 "xyz.openbmc_project.ObjectMapper",
1280 "/xyz/openbmc_project/object_mapper",
1281 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1282 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1283}
1284
1285/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001286 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1287 * TPM is required for booting the host.
1288 *
1289 * @param[in] aResp Shared pointer for generating response message.
1290 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1291 *
1292 * @return None.
1293 */
1294inline void setTrustedModuleRequiredToBoot(
1295 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1296{
1297 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1298
1299 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001300 [aResp, tpmRequired](const boost::system::error_code ec,
1301 dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001302 if (ec)
1303 {
1304 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1305 << ec;
1306 messages::internalError(aResp->res);
1307 return;
1308 }
1309 if (subtree.empty())
1310 {
1311 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1312 "TrustedModuleRequiredToBoot");
1313 return;
1314 }
1315
1316 /* When there is more than one TPMEnable object... */
1317 if (subtree.size() > 1)
1318 {
1319 BMCWEB_LOG_DEBUG
1320 << "DBUS response has more than 1 TPM Enable object:"
1321 << subtree.size();
1322 // Throw an internal Error and return
1323 messages::internalError(aResp->res);
1324 return;
1325 }
1326
1327 // Make sure the Dbus response map has a service and objectPath
1328 // field
1329 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1330 {
1331 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1332 messages::internalError(aResp->res);
1333 return;
1334 }
1335
1336 const std::string& path = subtree[0].first;
1337 const std::string& serv = subtree[0].second.begin()->first;
1338
1339 if (serv.empty())
1340 {
1341 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1342 messages::internalError(aResp->res);
1343 return;
1344 }
1345
1346 // Valid TPM Enable object found, now setting the value
1347 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07001348 [aResp](const boost::system::error_code ec2) {
1349 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001350 {
1351 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001352 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001353 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001354 messages::internalError(aResp->res);
1355 return;
1356 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001357 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1358 },
1359 serv, path, "org.freedesktop.DBus.Properties", "Set",
1360 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1361 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001362 },
1363 "xyz.openbmc_project.ObjectMapper",
1364 "/xyz/openbmc_project/object_mapper",
1365 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1366 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1367}
1368
1369/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301370 * @brief Sets boot properties into DBUS object(s).
1371 *
1372 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001373 * @param[in] bootType The boot type to set.
1374 * @return Integer error code.
1375 */
1376inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001377 const std::optional<std::string>& bootType)
1378{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001379 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001380
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001381 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001382 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001383 return;
1384 }
1385
1386 // Source target specified
1387 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1388 // Figure out which DBUS interface and property to use
1389 if (*bootType == "Legacy")
1390 {
1391 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1392 }
1393 else if (*bootType == "UEFI")
1394 {
1395 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1396 }
1397 else
1398 {
1399 BMCWEB_LOG_DEBUG << "Invalid property value for "
1400 "BootSourceOverrideMode: "
1401 << *bootType;
1402 messages::propertyValueNotInList(aResp->res, *bootType,
1403 "BootSourceOverrideMode");
1404 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001405 }
1406
1407 // Act on validated parameters
1408 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1409
1410 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001411 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001412 if (ec)
1413 {
1414 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1415 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001416 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001417 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001418 return;
1419 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001420 messages::internalError(aResp->res);
1421 return;
1422 }
1423 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001424 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001425 "xyz.openbmc_project.Settings",
1426 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001427 "org.freedesktop.DBus.Properties", "Set",
1428 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001429 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001430}
1431
1432/**
1433 * @brief Sets boot properties into DBUS object(s).
1434 *
1435 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001436 * @param[in] bootType The boot type to set.
1437 * @return Integer error code.
1438 */
1439inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1440 const std::optional<std::string>& bootEnable)
1441{
1442 if (!bootEnable)
1443 {
1444 return;
1445 }
1446 // Source target specified
1447 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1448
1449 bool bootOverrideEnable = false;
1450 bool bootOverridePersistent = false;
1451 // Figure out which DBUS interface and property to use
1452 if (*bootEnable == "Disabled")
1453 {
1454 bootOverrideEnable = false;
1455 }
1456 else if (*bootEnable == "Once")
1457 {
1458 bootOverrideEnable = true;
1459 bootOverridePersistent = false;
1460 }
1461 else if (*bootEnable == "Continuous")
1462 {
1463 bootOverrideEnable = true;
1464 bootOverridePersistent = true;
1465 }
1466 else
1467 {
George Liu0fda0f12021-11-16 10:06:17 +08001468 BMCWEB_LOG_DEBUG
1469 << "Invalid property value for BootSourceOverrideEnabled: "
1470 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001471 messages::propertyValueNotInList(aResp->res, *bootEnable,
1472 "BootSourceOverrideEnabled");
1473 return;
1474 }
1475
1476 // Act on validated parameters
1477 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1478
1479 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07001480 [aResp](const boost::system::error_code ec2) {
1481 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001482 {
Ed Tanous8a592812022-06-04 09:06:59 -07001483 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001484 messages::internalError(aResp->res);
1485 return;
1486 }
1487 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001488 },
1489 "xyz.openbmc_project.Settings",
1490 "/xyz/openbmc_project/control/host0/boot",
1491 "org.freedesktop.DBus.Properties", "Set",
1492 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001493 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001494
1495 if (!bootOverrideEnable)
1496 {
1497 return;
1498 }
1499
1500 // In case boot override is enabled we need to set correct value for the
1501 // 'one_time' enable DBus interface
1502 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1503 << bootOverridePersistent;
1504
1505 crow::connections::systemBus->async_method_call(
1506 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001507 if (ec)
1508 {
1509 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1510 messages::internalError(aResp->res);
1511 return;
1512 }
1513 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001514 },
1515 "xyz.openbmc_project.Settings",
1516 "/xyz/openbmc_project/control/host0/boot/one_time",
1517 "org.freedesktop.DBus.Properties", "Set",
1518 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001519 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001520}
1521
1522/**
1523 * @brief Sets boot properties into DBUS object(s).
1524 *
1525 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301526 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301527 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001528 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301529 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001530inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001531 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301532{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001533 std::string bootSourceStr;
1534 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001535
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001536 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301537 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001538 return;
1539 }
1540
1541 // Source target specified
1542 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1543 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001544 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1545 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001546 {
1547 BMCWEB_LOG_DEBUG
1548 << "Invalid property value for BootSourceOverrideTarget: "
1549 << *bootSource;
1550 messages::propertyValueNotInList(aResp->res, *bootSource,
1551 "BootSourceTargetOverride");
1552 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001553 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301554
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001555 // Act on validated parameters
1556 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1557 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001558
1559 crow::connections::systemBus->async_method_call(
1560 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001561 if (ec)
1562 {
1563 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1564 messages::internalError(aResp->res);
1565 return;
1566 }
1567 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001568 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001569 "xyz.openbmc_project.Settings",
1570 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001571 "org.freedesktop.DBus.Properties", "Set",
1572 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001573 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001574
1575 crow::connections::systemBus->async_method_call(
1576 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001577 if (ec)
1578 {
1579 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1580 messages::internalError(aResp->res);
1581 return;
1582 }
1583 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001584 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001585 "xyz.openbmc_project.Settings",
1586 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001587 "org.freedesktop.DBus.Properties", "Set",
1588 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001589 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001590}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001591
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001592/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001593 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301594 *
1595 * @param[in] aResp Shared pointer for generating response message.
1596 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001597 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301598 * @param[in] bootEnable The boot override enable from incoming RF request.
1599 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001600 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301601 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001602
1603inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1604 const std::optional<std::string>& bootSource,
1605 const std::optional<std::string>& bootType,
1606 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301607{
1608 BMCWEB_LOG_DEBUG << "Set boot information.";
1609
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001610 setBootModeOrSource(aResp, bootSource);
1611 setBootType(aResp, bootType);
1612 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301613}
1614
George Liuc6a620f2020-04-10 17:18:11 +08001615/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001616 * @brief Sets AssetTag
1617 *
1618 * @param[in] aResp Shared pointer for generating response message.
1619 * @param[in] assetTag "AssetTag" from request.
1620 *
1621 * @return None.
1622 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001623inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001624 const std::string& assetTag)
1625{
1626 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001627 [aResp,
1628 assetTag](const boost::system::error_code ec,
1629 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001630 if (ec)
1631 {
1632 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1633 messages::internalError(aResp->res);
1634 return;
1635 }
1636 if (subtree.empty())
1637 {
1638 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1639 messages::internalError(aResp->res);
1640 return;
1641 }
1642 // Assume only 1 system D-Bus object
1643 // Throw an error if there is more than 1
1644 if (subtree.size() > 1)
1645 {
1646 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1647 messages::internalError(aResp->res);
1648 return;
1649 }
1650 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1651 {
1652 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1653 messages::internalError(aResp->res);
1654 return;
1655 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001656
Ed Tanous002d39b2022-05-31 08:59:27 -07001657 const std::string& path = subtree[0].first;
1658 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001659
Ed Tanous002d39b2022-05-31 08:59:27 -07001660 if (service.empty())
1661 {
1662 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1663 messages::internalError(aResp->res);
1664 return;
1665 }
1666
1667 crow::connections::systemBus->async_method_call(
1668 [aResp](const boost::system::error_code ec2) {
1669 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001670 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001671 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1672 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001673 messages::internalError(aResp->res);
1674 return;
1675 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001676 },
1677 service, path, "org.freedesktop.DBus.Properties", "Set",
1678 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1679 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001680 },
1681 "xyz.openbmc_project.ObjectMapper",
1682 "/xyz/openbmc_project/object_mapper",
1683 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1684 "/xyz/openbmc_project/inventory", int32_t(0),
1685 std::array<const char*, 1>{
1686 "xyz.openbmc_project.Inventory.Item.System"});
1687}
1688
1689/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001690 * @brief Sets automaticRetry (Auto Reboot)
1691 *
1692 * @param[in] aResp Shared pointer for generating response message.
1693 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1694 *
1695 * @return None.
1696 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001697inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001698 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001699{
1700 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1701
1702 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001703 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001704
1705 if (automaticRetryConfig == "Disabled")
1706 {
1707 autoRebootEnabled = false;
1708 }
1709 else if (automaticRetryConfig == "RetryAttempts")
1710 {
1711 autoRebootEnabled = true;
1712 }
1713 else
1714 {
George Liu0fda0f12021-11-16 10:06:17 +08001715 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001716 << automaticRetryConfig;
1717 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1718 "AutomaticRetryConfig");
1719 return;
1720 }
1721
1722 crow::connections::systemBus->async_method_call(
1723 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001724 if (ec)
1725 {
1726 messages::internalError(aResp->res);
1727 return;
1728 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001729 },
1730 "xyz.openbmc_project.Settings",
1731 "/xyz/openbmc_project/control/host0/auto_reboot",
1732 "org.freedesktop.DBus.Properties", "Set",
1733 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001734 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001735}
1736
1737/**
George Liuc6a620f2020-04-10 17:18:11 +08001738 * @brief Sets power restore policy properties.
1739 *
1740 * @param[in] aResp Shared pointer for generating response message.
1741 * @param[in] policy power restore policy properties from request.
1742 *
1743 * @return None.
1744 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001745inline void
1746 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1747 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001748{
1749 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1750
1751 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001752 {"AlwaysOn",
1753 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1754 {"AlwaysOff",
1755 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1756 {"LastState",
1757 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001758
1759 std::string powerRestorPolicy;
1760
Gunnar Mills4e69c902021-01-05 19:50:11 -06001761 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001762 if (policyMapsIt == policyMaps.end())
1763 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001764 messages::propertyValueNotInList(aResp->res, policy,
1765 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001766 return;
1767 }
1768
1769 powerRestorPolicy = policyMapsIt->second;
1770
1771 crow::connections::systemBus->async_method_call(
1772 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001773 if (ec)
1774 {
1775 messages::internalError(aResp->res);
1776 return;
1777 }
George Liuc6a620f2020-04-10 17:18:11 +08001778 },
1779 "xyz.openbmc_project.Settings",
1780 "/xyz/openbmc_project/control/host0/power_restore_policy",
1781 "org.freedesktop.DBus.Properties", "Set",
1782 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001783 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001784}
1785
AppaRao Pulia6349912019-10-18 17:16:08 +05301786#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1787/**
1788 * @brief Retrieves provisioning status
1789 *
1790 * @param[in] aResp Shared pointer for completing asynchronous calls.
1791 *
1792 * @return None.
1793 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001794inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301795{
1796 BMCWEB_LOG_DEBUG << "Get OEM information.";
1797 crow::connections::systemBus->async_method_call(
1798 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001799 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001800 nlohmann::json& oemPFR =
1801 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1802 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1803 "#OemComputerSystem.OpenBmc";
1804 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001805
Ed Tanous002d39b2022-05-31 08:59:27 -07001806 if (ec)
1807 {
1808 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1809 // not an error, don't have to have the interface
1810 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1811 return;
1812 }
1813
1814 const bool* provState = nullptr;
1815 const bool* lockState = nullptr;
1816 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1817 property : propertiesList)
1818 {
1819 if (property.first == "UfmProvisioned")
AppaRao Pulia6349912019-10-18 17:16:08 +05301820 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001821 provState = std::get_if<bool>(&property.second);
AppaRao Pulia6349912019-10-18 17:16:08 +05301822 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001823 else if (property.first == "UfmLocked")
AppaRao Pulia6349912019-10-18 17:16:08 +05301824 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001825 lockState = std::get_if<bool>(&property.second);
AppaRao Pulia6349912019-10-18 17:16:08 +05301826 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001827 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301828
Ed Tanous002d39b2022-05-31 08:59:27 -07001829 if ((provState == nullptr) || (lockState == nullptr))
1830 {
1831 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1832 messages::internalError(aResp->res);
1833 return;
1834 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301835
Ed Tanous002d39b2022-05-31 08:59:27 -07001836 if (*provState == true)
1837 {
1838 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301839 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001840 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301841 }
1842 else
1843 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001844 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301845 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001846 }
1847 else
1848 {
1849 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1850 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301851 },
1852 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1853 "org.freedesktop.DBus.Properties", "GetAll",
1854 "xyz.openbmc_project.PFR.Attributes");
1855}
1856#endif
1857
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301858/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001859 * @brief Translate the PowerMode to a response message.
1860 *
1861 * @param[in] aResp Shared pointer for generating response message.
1862 * @param[in] modeValue PowerMode value to be translated
1863 *
1864 * @return None.
1865 */
1866inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1867 const std::string& modeValue)
1868{
George Liu0fda0f12021-11-16 10:06:17 +08001869 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001870 {
1871 aResp->res.jsonValue["PowerMode"] = "Static";
1872 }
George Liu0fda0f12021-11-16 10:06:17 +08001873 else if (
1874 modeValue ==
1875 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001876 {
1877 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1878 }
George Liu0fda0f12021-11-16 10:06:17 +08001879 else if (modeValue ==
1880 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001881 {
1882 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1883 }
George Liu0fda0f12021-11-16 10:06:17 +08001884 else if (modeValue ==
1885 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001886 {
1887 aResp->res.jsonValue["PowerMode"] = "OEM";
1888 }
1889 else
1890 {
1891 // Any other values would be invalid
1892 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1893 messages::internalError(aResp->res);
1894 }
1895}
1896
1897/**
1898 * @brief Retrieves system power mode
1899 *
1900 * @param[in] aResp Shared pointer for generating response message.
1901 *
1902 * @return None.
1903 */
1904inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1905{
1906 BMCWEB_LOG_DEBUG << "Get power mode.";
1907
1908 // Get Power Mode object path:
1909 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001910 [aResp](const boost::system::error_code ec,
1911 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001912 if (ec)
1913 {
1914 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
1915 << ec;
1916 // This is an optional D-Bus object so just return if
1917 // error occurs
1918 return;
1919 }
1920 if (subtree.empty())
1921 {
1922 // As noted above, this is an optional interface so just return
1923 // if there is no instance found
1924 return;
1925 }
1926 if (subtree.size() > 1)
1927 {
1928 // More then one PowerMode object is not supported and is an
1929 // error
1930 BMCWEB_LOG_DEBUG
1931 << "Found more than 1 system D-Bus Power.Mode objects: "
1932 << subtree.size();
1933 messages::internalError(aResp->res);
1934 return;
1935 }
1936 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1937 {
1938 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1939 messages::internalError(aResp->res);
1940 return;
1941 }
1942 const std::string& path = subtree[0].first;
1943 const std::string& service = subtree[0].second.begin()->first;
1944 if (service.empty())
1945 {
1946 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1947 messages::internalError(aResp->res);
1948 return;
1949 }
1950 // Valid Power Mode object found, now read the current value
1951 sdbusplus::asio::getProperty<std::string>(
1952 *crow::connections::systemBus, service, path,
1953 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous8a592812022-06-04 09:06:59 -07001954 [aResp](const boost::system::error_code ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07001955 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07001956 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05001957 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001958 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07001959 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05001960 messages::internalError(aResp->res);
1961 return;
1962 }
Chris Cain3a2d04242021-05-28 16:57:10 -05001963
Ed Tanous002d39b2022-05-31 08:59:27 -07001964 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
1965 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05001966
Ed Tanous002d39b2022-05-31 08:59:27 -07001967 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1968 translatePowerMode(aResp, pmode);
1969 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001970 },
1971 "xyz.openbmc_project.ObjectMapper",
1972 "/xyz/openbmc_project/object_mapper",
1973 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1974 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1975}
1976
1977/**
1978 * @brief Validate the specified mode is valid and return the PowerMode
1979 * name associated with that string
1980 *
1981 * @param[in] aResp Shared pointer for generating response message.
1982 * @param[in] modeString String representing the desired PowerMode
1983 *
1984 * @return PowerMode value or empty string if mode is not valid
1985 */
1986inline std::string
1987 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1988 const std::string& modeString)
1989{
1990 std::string mode;
1991
1992 if (modeString == "Static")
1993 {
1994 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
1995 }
1996 else if (modeString == "MaximumPerformance")
1997 {
George Liu0fda0f12021-11-16 10:06:17 +08001998 mode =
1999 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002000 }
2001 else if (modeString == "PowerSaving")
2002 {
2003 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2004 }
2005 else
2006 {
2007 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2008 }
2009 return mode;
2010}
2011
2012/**
2013 * @brief Sets system power mode.
2014 *
2015 * @param[in] aResp Shared pointer for generating response message.
2016 * @param[in] pmode System power mode from request.
2017 *
2018 * @return None.
2019 */
2020inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2021 const std::string& pmode)
2022{
2023 BMCWEB_LOG_DEBUG << "Set power mode.";
2024
2025 std::string powerMode = validatePowerMode(aResp, pmode);
2026 if (powerMode.empty())
2027 {
2028 return;
2029 }
2030
2031 // Get Power Mode object path:
2032 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002033 [aResp,
2034 powerMode](const boost::system::error_code ec,
2035 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002036 if (ec)
2037 {
2038 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2039 << ec;
2040 // This is an optional D-Bus object, but user attempted to patch
2041 messages::internalError(aResp->res);
2042 return;
2043 }
2044 if (subtree.empty())
2045 {
2046 // This is an optional D-Bus object, but user attempted to patch
2047 messages::resourceNotFound(aResp->res, "ComputerSystem",
2048 "PowerMode");
2049 return;
2050 }
2051 if (subtree.size() > 1)
2052 {
2053 // More then one PowerMode object is not supported and is an
2054 // error
2055 BMCWEB_LOG_DEBUG
2056 << "Found more than 1 system D-Bus Power.Mode objects: "
2057 << subtree.size();
2058 messages::internalError(aResp->res);
2059 return;
2060 }
2061 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2062 {
2063 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2064 messages::internalError(aResp->res);
2065 return;
2066 }
2067 const std::string& path = subtree[0].first;
2068 const std::string& service = subtree[0].second.begin()->first;
2069 if (service.empty())
2070 {
2071 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2072 messages::internalError(aResp->res);
2073 return;
2074 }
2075
2076 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2077 << path;
2078
2079 // Set the Power Mode property
2080 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002081 [aResp](const boost::system::error_code ec2) {
2082 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002083 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002084 messages::internalError(aResp->res);
2085 return;
2086 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002087 },
2088 service, path, "org.freedesktop.DBus.Properties", "Set",
2089 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2090 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002091 },
2092 "xyz.openbmc_project.ObjectMapper",
2093 "/xyz/openbmc_project/object_mapper",
2094 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2095 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2096}
2097
2098/**
Yong Li51709ff2019-09-30 14:13:04 +08002099 * @brief Translates watchdog timeout action DBUS property value to redfish.
2100 *
2101 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2102 *
2103 * @return Returns as a string, the timeout action in Redfish terms. If
2104 * translation cannot be done, returns an empty string.
2105 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002106inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002107{
2108 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2109 {
2110 return "None";
2111 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002112 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002113 {
2114 return "ResetSystem";
2115 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002116 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002117 {
2118 return "PowerDown";
2119 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002120 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002121 {
2122 return "PowerCycle";
2123 }
2124
2125 return "";
2126}
2127
2128/**
Yong Lic45f0082019-10-10 14:19:01 +08002129 *@brief Translates timeout action from Redfish to DBUS property value.
2130 *
2131 *@param[in] rfAction The timeout action in Redfish.
2132 *
2133 *@return Returns as a string, the time_out action as expected by DBUS.
2134 *If translation cannot be done, returns an empty string.
2135 */
2136
Ed Tanous23a21a12020-07-25 04:45:05 +00002137inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002138{
2139 if (rfAction == "None")
2140 {
2141 return "xyz.openbmc_project.State.Watchdog.Action.None";
2142 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002143 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002144 {
2145 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2146 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002147 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002148 {
2149 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2150 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002151 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002152 {
2153 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2154 }
2155
2156 return "";
2157}
2158
2159/**
Yong Li51709ff2019-09-30 14:13:04 +08002160 * @brief Retrieves host watchdog timer properties over DBUS
2161 *
2162 * @param[in] aResp Shared pointer for completing asynchronous calls.
2163 *
2164 * @return None.
2165 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002166inline void
2167 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002168{
2169 BMCWEB_LOG_DEBUG << "Get host watchodg";
2170 crow::connections::systemBus->async_method_call(
2171 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002172 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002173 if (ec)
2174 {
2175 // watchdog service is stopped
2176 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2177 return;
2178 }
2179
2180 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2181
2182 nlohmann::json& hostWatchdogTimer =
2183 aResp->res.jsonValue["HostWatchdogTimer"];
2184
2185 // watchdog service is running/enabled
2186 hostWatchdogTimer["Status"]["State"] = "Enabled";
2187
2188 for (const auto& property : properties)
2189 {
2190 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2191 if (property.first == "Enabled")
Yong Li51709ff2019-09-30 14:13:04 +08002192 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002193 const bool* state = std::get_if<bool>(&property.second);
2194
2195 if (state == nullptr)
2196 {
2197 messages::internalError(aResp->res);
2198 return;
2199 }
2200
2201 hostWatchdogTimer["FunctionEnabled"] = *state;
Yong Li51709ff2019-09-30 14:13:04 +08002202 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002203 else if (property.first == "ExpireAction")
Yong Li51709ff2019-09-30 14:13:04 +08002204 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002205 const std::string* s =
2206 std::get_if<std::string>(&property.second);
2207 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002208 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002209 messages::internalError(aResp->res);
2210 return;
Yong Li51709ff2019-09-30 14:13:04 +08002211 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002212
2213 std::string action = dbusToRfWatchdogAction(*s);
2214 if (action.empty())
Yong Li51709ff2019-09-30 14:13:04 +08002215 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002216 messages::internalError(aResp->res);
2217 return;
Yong Li51709ff2019-09-30 14:13:04 +08002218 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002219 hostWatchdogTimer["TimeoutAction"] = action;
Yong Li51709ff2019-09-30 14:13:04 +08002220 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002221 }
Yong Li51709ff2019-09-30 14:13:04 +08002222 },
2223 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2224 "org.freedesktop.DBus.Properties", "GetAll",
2225 "xyz.openbmc_project.State.Watchdog");
2226}
2227
2228/**
Yong Lic45f0082019-10-10 14:19:01 +08002229 * @brief Sets Host WatchDog Timer properties.
2230 *
2231 * @param[in] aResp Shared pointer for generating response message.
2232 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2233 * RF request.
2234 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2235 *
2236 * @return None.
2237 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002238inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002239 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002240 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002241{
2242 BMCWEB_LOG_DEBUG << "Set host watchdog";
2243
2244 if (wdtTimeOutAction)
2245 {
2246 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2247 // check if TimeOut Action is Valid
2248 if (wdtTimeOutActStr.empty())
2249 {
2250 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2251 << *wdtTimeOutAction;
2252 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2253 "TimeoutAction");
2254 return;
2255 }
2256
2257 crow::connections::systemBus->async_method_call(
2258 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002259 if (ec)
2260 {
2261 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2262 messages::internalError(aResp->res);
2263 return;
2264 }
Yong Lic45f0082019-10-10 14:19:01 +08002265 },
2266 "xyz.openbmc_project.Watchdog",
2267 "/xyz/openbmc_project/watchdog/host0",
2268 "org.freedesktop.DBus.Properties", "Set",
2269 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002270 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002271 }
2272
2273 if (wdtEnable)
2274 {
2275 crow::connections::systemBus->async_method_call(
2276 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002277 if (ec)
2278 {
2279 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2280 messages::internalError(aResp->res);
2281 return;
2282 }
Yong Lic45f0082019-10-10 14:19:01 +08002283 },
2284 "xyz.openbmc_project.Watchdog",
2285 "/xyz/openbmc_project/watchdog/host0",
2286 "org.freedesktop.DBus.Properties", "Set",
2287 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002288 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002289 }
2290}
2291
Chris Cain37bbf982021-09-20 10:53:09 -05002292/**
2293 * @brief Parse the Idle Power Saver properties into json
2294 *
2295 * @param[in] aResp Shared pointer for completing asynchronous calls.
2296 * @param[in] properties IPS property data from DBus.
2297 *
2298 * @return true if successful
2299 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002300inline bool
2301 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2302 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002303{
2304 for (const auto& property : properties)
2305 {
2306 if (property.first == "Enabled")
2307 {
2308 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002309 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002310 {
2311 return false;
2312 }
2313 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2314 }
2315 else if (property.first == "EnterUtilizationPercent")
2316 {
2317 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002318 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002319 {
2320 return false;
2321 }
2322 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2323 }
2324 else if (property.first == "EnterDwellTime")
2325 {
2326 // Convert Dbus time from milliseconds to seconds
2327 const uint64_t* timeMilliseconds =
2328 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002329 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002330 {
2331 return false;
2332 }
2333 const std::chrono::duration<uint64_t, std::milli> ms(
2334 *timeMilliseconds);
2335 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2336 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2337 .count();
2338 }
2339 else if (property.first == "ExitUtilizationPercent")
2340 {
2341 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002342 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002343 {
2344 return false;
2345 }
2346 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2347 }
2348 else if (property.first == "ExitDwellTime")
2349 {
2350 // Convert Dbus time from milliseconds to seconds
2351 const uint64_t* timeMilliseconds =
2352 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002353 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002354 {
2355 return false;
2356 }
2357 const std::chrono::duration<uint64_t, std::milli> ms(
2358 *timeMilliseconds);
2359 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2360 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2361 .count();
2362 }
2363 else
2364 {
2365 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2366 << property.first;
2367 }
2368 }
2369
2370 return true;
2371}
2372
2373/**
2374 * @brief Retrieves host watchdog timer properties over DBUS
2375 *
2376 * @param[in] aResp Shared pointer for completing asynchronous calls.
2377 *
2378 * @return None.
2379 */
2380inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2381{
2382 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2383
2384 // Get IdlePowerSaver object path:
2385 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002386 [aResp](const boost::system::error_code ec,
2387 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002388 if (ec)
2389 {
2390 BMCWEB_LOG_DEBUG
2391 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2392 << ec;
2393 messages::internalError(aResp->res);
2394 return;
2395 }
2396 if (subtree.empty())
2397 {
2398 // This is an optional interface so just return
2399 // if there is no instance found
2400 BMCWEB_LOG_DEBUG << "No instances found";
2401 return;
2402 }
2403 if (subtree.size() > 1)
2404 {
2405 // More then one PowerIdlePowerSaver object is not supported and
2406 // is an error
2407 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2408 "Power.IdlePowerSaver objects: "
2409 << subtree.size();
2410 messages::internalError(aResp->res);
2411 return;
2412 }
2413 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2414 {
2415 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2416 messages::internalError(aResp->res);
2417 return;
2418 }
2419 const std::string& path = subtree[0].first;
2420 const std::string& service = subtree[0].second.begin()->first;
2421 if (service.empty())
2422 {
2423 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2424 messages::internalError(aResp->res);
2425 return;
2426 }
2427
2428 // Valid IdlePowerSaver object found, now read the current values
2429 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002430 [aResp](const boost::system::error_code ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002431 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002432 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002433 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002434 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002435 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002436 messages::internalError(aResp->res);
2437 return;
2438 }
2439
Ed Tanous002d39b2022-05-31 08:59:27 -07002440 if (!parseIpsProperties(aResp, properties))
2441 {
2442 messages::internalError(aResp->res);
2443 return;
2444 }
2445 },
2446 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2447 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
Chris Cain37bbf982021-09-20 10:53:09 -05002448 },
2449 "xyz.openbmc_project.ObjectMapper",
2450 "/xyz/openbmc_project/object_mapper",
2451 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2452 std::array<const char*, 1>{
2453 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2454
2455 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2456}
2457
2458/**
2459 * @brief Sets Idle Power Saver properties.
2460 *
2461 * @param[in] aResp Shared pointer for generating response message.
2462 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2463 * RF request.
2464 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2465 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2466 * before entering idle state.
2467 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2468 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2469 * before exiting idle state
2470 *
2471 * @return None.
2472 */
2473inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2474 const std::optional<bool> ipsEnable,
2475 const std::optional<uint8_t> ipsEnterUtil,
2476 const std::optional<uint64_t> ipsEnterTime,
2477 const std::optional<uint8_t> ipsExitUtil,
2478 const std::optional<uint64_t> ipsExitTime)
2479{
2480 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2481
2482 // Get IdlePowerSaver object path:
2483 crow::connections::systemBus->async_method_call(
2484 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002485 ipsExitTime](const boost::system::error_code ec,
2486 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002487 if (ec)
2488 {
2489 BMCWEB_LOG_DEBUG
2490 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2491 << ec;
2492 messages::internalError(aResp->res);
2493 return;
2494 }
2495 if (subtree.empty())
2496 {
2497 // This is an optional D-Bus object, but user attempted to patch
2498 messages::resourceNotFound(aResp->res, "ComputerSystem",
2499 "IdlePowerSaver");
2500 return;
2501 }
2502 if (subtree.size() > 1)
2503 {
2504 // More then one PowerIdlePowerSaver object is not supported and
2505 // is an error
2506 BMCWEB_LOG_DEBUG
2507 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2508 << subtree.size();
2509 messages::internalError(aResp->res);
2510 return;
2511 }
2512 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2513 {
2514 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2515 messages::internalError(aResp->res);
2516 return;
2517 }
2518 const std::string& path = subtree[0].first;
2519 const std::string& service = subtree[0].second.begin()->first;
2520 if (service.empty())
2521 {
2522 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2523 messages::internalError(aResp->res);
2524 return;
2525 }
Chris Cain37bbf982021-09-20 10:53:09 -05002526
Ed Tanous002d39b2022-05-31 08:59:27 -07002527 // Valid Power IdlePowerSaver object found, now set any values that
2528 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002529
Ed Tanous002d39b2022-05-31 08:59:27 -07002530 if (ipsEnable)
2531 {
2532 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002533 [aResp](const boost::system::error_code ec2) {
2534 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002535 {
Ed Tanous8a592812022-06-04 09:06:59 -07002536 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002537 messages::internalError(aResp->res);
2538 return;
2539 }
2540 },
2541 service, path, "org.freedesktop.DBus.Properties", "Set",
2542 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2543 dbus::utility::DbusVariantType(*ipsEnable));
2544 }
2545 if (ipsEnterUtil)
2546 {
2547 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002548 [aResp](const boost::system::error_code ec2) {
2549 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002550 {
Ed Tanous8a592812022-06-04 09:06:59 -07002551 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002552 messages::internalError(aResp->res);
2553 return;
2554 }
2555 },
2556 service, path, "org.freedesktop.DBus.Properties", "Set",
2557 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2558 "EnterUtilizationPercent",
2559 dbus::utility::DbusVariantType(*ipsEnterUtil));
2560 }
2561 if (ipsEnterTime)
2562 {
2563 // Convert from seconds into milliseconds for DBus
2564 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2565 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002566 [aResp](const boost::system::error_code ec2) {
2567 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002568 {
Ed Tanous8a592812022-06-04 09:06:59 -07002569 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002570 messages::internalError(aResp->res);
2571 return;
2572 }
2573 },
2574 service, path, "org.freedesktop.DBus.Properties", "Set",
2575 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2576 "EnterDwellTime",
2577 dbus::utility::DbusVariantType(timeMilliseconds));
2578 }
2579 if (ipsExitUtil)
2580 {
2581 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002582 [aResp](const boost::system::error_code ec2) {
2583 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002584 {
Ed Tanous8a592812022-06-04 09:06:59 -07002585 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002586 messages::internalError(aResp->res);
2587 return;
2588 }
2589 },
2590 service, path, "org.freedesktop.DBus.Properties", "Set",
2591 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2592 "ExitUtilizationPercent",
2593 dbus::utility::DbusVariantType(*ipsExitUtil));
2594 }
2595 if (ipsExitTime)
2596 {
2597 // Convert from seconds into milliseconds for DBus
2598 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2599 crow::connections::systemBus->async_method_call(
Ed Tanous8a592812022-06-04 09:06:59 -07002600 [aResp](const boost::system::error_code ec2) {
2601 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002602 {
Ed Tanous8a592812022-06-04 09:06:59 -07002603 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002604 messages::internalError(aResp->res);
2605 return;
2606 }
2607 },
2608 service, path, "org.freedesktop.DBus.Properties", "Set",
2609 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2610 "ExitDwellTime",
2611 dbus::utility::DbusVariantType(timeMilliseconds));
2612 }
Chris Cain37bbf982021-09-20 10:53:09 -05002613 },
2614 "xyz.openbmc_project.ObjectMapper",
2615 "/xyz/openbmc_project/object_mapper",
2616 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2617 std::array<const char*, 1>{
2618 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2619
2620 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2621}
2622
Yong Lic45f0082019-10-10 14:19:01 +08002623/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002624 * SystemsCollection derived class for delivering ComputerSystems Collection
2625 * Schema
2626 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002627inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002628{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002629 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002630 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002631 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002632 [&app](const crow::Request& req,
2633 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002634 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002635 {
2636 return;
2637 }
2638 asyncResp->res.jsonValue["@odata.type"] =
2639 "#ComputerSystemCollection.ComputerSystemCollection";
2640 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2641 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002642
Ed Tanous002d39b2022-05-31 08:59:27 -07002643 sdbusplus::asio::getProperty<std::string>(
2644 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2645 "/xyz/openbmc_project/network/hypervisor",
2646 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous8a592812022-06-04 09:06:59 -07002647 [asyncResp](const boost::system::error_code ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002648 const std::string& /*hostName*/) {
2649 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2650 ifaceArray = nlohmann::json::array();
2651 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002652
Ed Tanous002d39b2022-05-31 08:59:27 -07002653 nlohmann::json::object_t system;
2654 system["@odata.id"] = "/redfish/v1/Systems/system";
2655 ifaceArray.push_back(std::move(system));
2656 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002657 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002658 {
2659 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2660 nlohmann::json::object_t hypervisor;
2661 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2662 ifaceArray.push_back(std::move(hypervisor));
2663 count = ifaceArray.size();
2664 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002665 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002666 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002667}
Sunitha Harish462023a2020-02-19 08:34:59 -06002668
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002669/**
2670 * Function transceives data with dbus directly.
2671 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002672inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002673{
2674 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2675 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2676 constexpr char const* interfaceName =
2677 "xyz.openbmc_project.Control.Host.NMI";
2678 constexpr char const* method = "NMI";
2679
2680 crow::connections::systemBus->async_method_call(
2681 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002682 if (ec)
2683 {
2684 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2685 messages::internalError(asyncResp->res);
2686 return;
2687 }
2688 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002689 },
2690 serviceName, objectPath, interfaceName, method);
2691}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002692
2693/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002694 * SystemActionsReset class supports handle POST method for Reset action.
2695 * The class retrieves and sends data directly to D-Bus.
2696 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002697inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002698{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002699 /**
2700 * Function handles POST method request.
2701 * Analyzes POST body message before sends Reset request data to D-Bus.
2702 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002703 BMCWEB_ROUTE(app,
2704 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002705 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002706 .methods(boost::beast::http::verb::post)(
2707 [&app](const crow::Request& req,
2708 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002709 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002710 {
2711 return;
2712 }
2713 std::string resetType;
2714 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2715 resetType))
2716 {
2717 return;
2718 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002719
Ed Tanous002d39b2022-05-31 08:59:27 -07002720 // Get the command and host vs. chassis
2721 std::string command;
2722 bool hostCommand = true;
2723 if ((resetType == "On") || (resetType == "ForceOn"))
2724 {
2725 command = "xyz.openbmc_project.State.Host.Transition.On";
2726 hostCommand = true;
2727 }
2728 else if (resetType == "ForceOff")
2729 {
2730 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2731 hostCommand = false;
2732 }
2733 else if (resetType == "ForceRestart")
2734 {
2735 command =
2736 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2737 hostCommand = true;
2738 }
2739 else if (resetType == "GracefulShutdown")
2740 {
2741 command = "xyz.openbmc_project.State.Host.Transition.Off";
2742 hostCommand = true;
2743 }
2744 else if (resetType == "GracefulRestart")
2745 {
2746 command =
2747 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2748 hostCommand = true;
2749 }
2750 else if (resetType == "PowerCycle")
2751 {
2752 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2753 hostCommand = true;
2754 }
2755 else if (resetType == "Nmi")
2756 {
2757 doNMI(asyncResp);
2758 return;
2759 }
2760 else
2761 {
2762 messages::actionParameterUnknown(asyncResp->res, "Reset",
2763 resetType);
2764 return;
2765 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002766
Ed Tanous002d39b2022-05-31 08:59:27 -07002767 if (hostCommand)
2768 {
2769 crow::connections::systemBus->async_method_call(
2770 [asyncResp, resetType](const boost::system::error_code ec) {
2771 if (ec)
2772 {
2773 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2774 if (ec.value() == boost::asio::error::invalid_argument)
2775 {
2776 messages::actionParameterNotSupported(
2777 asyncResp->res, resetType, "Reset");
2778 }
2779 else
2780 {
2781 messages::internalError(asyncResp->res);
2782 }
2783 return;
2784 }
2785 messages::success(asyncResp->res);
2786 },
2787 "xyz.openbmc_project.State.Host",
2788 "/xyz/openbmc_project/state/host0",
2789 "org.freedesktop.DBus.Properties", "Set",
2790 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2791 dbus::utility::DbusVariantType{command});
2792 }
2793 else
2794 {
2795 crow::connections::systemBus->async_method_call(
2796 [asyncResp, resetType](const boost::system::error_code ec) {
2797 if (ec)
2798 {
2799 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2800 if (ec.value() == boost::asio::error::invalid_argument)
2801 {
2802 messages::actionParameterNotSupported(
2803 asyncResp->res, resetType, "Reset");
2804 }
2805 else
2806 {
2807 messages::internalError(asyncResp->res);
2808 }
2809 return;
2810 }
2811 messages::success(asyncResp->res);
2812 },
2813 "xyz.openbmc_project.State.Chassis",
2814 "/xyz/openbmc_project/state/chassis0",
2815 "org.freedesktop.DBus.Properties", "Set",
2816 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2817 dbus::utility::DbusVariantType{command});
2818 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 });
2820}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002821
2822/**
Ed Tanous66173382018-08-15 18:20:59 -07002823 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002824 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002825inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002826{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002827
Ed Tanous1abe55e2018-09-05 08:30:59 -07002828 /**
2829 * Functions triggers appropriate requests on DBus
2830 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002832 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002833 .methods(boost::beast::http::verb::get)(
2834 [&app](const crow::Request& req,
2835 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002836 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002837 {
2838 return;
2839 }
2840 asyncResp->res.jsonValue["@odata.type"] =
2841 "#ComputerSystem.v1_16_0.ComputerSystem";
2842 asyncResp->res.jsonValue["Name"] = "system";
2843 asyncResp->res.jsonValue["Id"] = "system";
2844 asyncResp->res.jsonValue["SystemType"] = "Physical";
2845 asyncResp->res.jsonValue["Description"] = "Computer System";
2846 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2847 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2848 "Disabled";
2849 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2850 uint64_t(0);
2851 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2852 "Disabled";
2853 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002854
Ed Tanous002d39b2022-05-31 08:59:27 -07002855 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
2856 "/redfish/v1/Systems/system/Processors";
2857 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
2858 "/redfish/v1/Systems/system/Memory";
2859 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
2860 "/redfish/v1/Systems/system/Storage";
Ed Tanous029573d2019-02-01 10:57:49 -08002861
Ed Tanous002d39b2022-05-31 08:59:27 -07002862 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
2863 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
2864 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
2865 ["@Redfish.ActionInfo"] =
2866 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002867
Ed Tanous002d39b2022-05-31 08:59:27 -07002868 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
2869 "/redfish/v1/Systems/system/LogServices";
2870 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
2871 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002872
Ed Tanous002d39b2022-05-31 08:59:27 -07002873 nlohmann::json::array_t managedBy;
2874 nlohmann::json& manager = managedBy.emplace_back();
2875 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
2876 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
2877 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
2878 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002879
Ed Tanous002d39b2022-05-31 08:59:27 -07002880 // Fill in SerialConsole info
2881 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
2882 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
2883 true;
Ed Tanous14766872022-03-15 10:44:42 -07002884
Ed Tanous002d39b2022-05-31 08:59:27 -07002885 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2886 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
2887 true;
2888 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
2889 asyncResp->res
2890 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
2891 "Press ~. to exit console";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002892
2893#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002894 // Fill in GraphicalConsole info
2895 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
2896 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
2897 4;
2898 asyncResp->res
2899 .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"};
Ed Tanous14766872022-03-15 10:44:42 -07002900
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002901#endif // BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002902 constexpr const std::array<const char*, 4> inventoryForSystems = {
2903 "xyz.openbmc_project.Inventory.Item.Dimm",
2904 "xyz.openbmc_project.Inventory.Item.Cpu",
2905 "xyz.openbmc_project.Inventory.Item.Drive",
2906 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002907
Ed Tanous002d39b2022-05-31 08:59:27 -07002908 auto health = std::make_shared<HealthPopulate>(asyncResp);
2909 crow::connections::systemBus->async_method_call(
2910 [health](const boost::system::error_code ec,
2911 const std::vector<std::string>& resp) {
2912 if (ec)
2913 {
2914 // no inventory
2915 return;
2916 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002917
Ed Tanous002d39b2022-05-31 08:59:27 -07002918 health->inventory = resp;
2919 },
2920 "xyz.openbmc_project.ObjectMapper",
2921 "/xyz/openbmc_project/object_mapper",
2922 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2923 int32_t(0), inventoryForSystems);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002924
Ed Tanous002d39b2022-05-31 08:59:27 -07002925 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002926
Ed Tanous002d39b2022-05-31 08:59:27 -07002927 getMainChassisId(asyncResp,
2928 [](const std::string& chassisId,
2929 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2930 nlohmann::json::array_t chassisArray;
2931 nlohmann::json& chassis = chassisArray.emplace_back();
2932 chassis["@odata.id"] = "/redfish/v1/Chassis/" + chassisId;
2933 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
2934 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002935
Ed Tanous002d39b2022-05-31 08:59:27 -07002936 getLocationIndicatorActive(asyncResp);
2937 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2938 getIndicatorLedState(asyncResp);
2939 getComputerSystem(asyncResp, health);
2940 getHostState(asyncResp);
2941 getBootProperties(asyncResp);
2942 getBootProgress(asyncResp);
2943 getPCIeDeviceList(asyncResp, "PCIeDevices");
2944 getHostWatchdogTimer(asyncResp);
2945 getPowerRestorePolicy(asyncResp);
2946 getAutomaticRetry(asyncResp);
2947 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002948#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07002949 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002950#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07002951 getTrustedModuleRequiredToBoot(asyncResp);
2952 getPowerMode(asyncResp);
2953 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002954 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002955
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002956 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002957 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002958 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002959 [&app](const crow::Request& req,
2960 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002961 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002962 {
2963 return;
2964 }
2965 std::optional<bool> locationIndicatorActive;
2966 std::optional<std::string> indicatorLed;
2967 std::optional<std::string> assetTag;
2968 std::optional<std::string> powerRestorePolicy;
2969 std::optional<std::string> powerMode;
2970 std::optional<bool> wdtEnable;
2971 std::optional<std::string> wdtTimeOutAction;
2972 std::optional<std::string> bootSource;
2973 std::optional<std::string> bootType;
2974 std::optional<std::string> bootEnable;
2975 std::optional<std::string> bootAutomaticRetry;
2976 std::optional<bool> bootTrustedModuleRequired;
2977 std::optional<bool> ipsEnable;
2978 std::optional<uint8_t> ipsEnterUtil;
2979 std::optional<uint64_t> ipsEnterTime;
2980 std::optional<uint8_t> ipsExitUtil;
2981 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002982
Ed Tanous002d39b2022-05-31 08:59:27 -07002983 // clang-format off
Jiaqing Zhaoaa6d4532022-06-02 17:47:58 +08002984 if (!json_util::readJsonPatch(
2985 req, asyncResp->res,
2986 "IndicatorLED", indicatorLed,
2987 "LocationIndicatorActive", locationIndicatorActive,
2988 "AssetTag", assetTag,
2989 "PowerRestorePolicy", powerRestorePolicy,
2990 "PowerMode", powerMode,
2991 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
2992 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
2993 "Boot/BootSourceOverrideTarget", bootSource,
2994 "Boot/BootSourceOverrideMode", bootType,
2995 "Boot/BootSourceOverrideEnabled", bootEnable,
2996 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
2997 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
2998 "IdlePowerSaver/Enabled", ipsEnable,
2999 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3000 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3001 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3002 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3003 {
3004 return;
3005 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003006 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003007
Ed Tanous002d39b2022-05-31 08:59:27 -07003008 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003009
Ed Tanous002d39b2022-05-31 08:59:27 -07003010 if (assetTag)
3011 {
3012 setAssetTag(asyncResp, *assetTag);
3013 }
James Feistb49ac872019-05-21 15:12:01 -07003014
Ed Tanous002d39b2022-05-31 08:59:27 -07003015 if (wdtEnable || wdtTimeOutAction)
3016 {
3017 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3018 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003019
Ed Tanous002d39b2022-05-31 08:59:27 -07003020 if (bootSource || bootType || bootEnable)
3021 {
3022 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3023 }
3024 if (bootAutomaticRetry)
3025 {
3026 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3027 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003028
Ed Tanous002d39b2022-05-31 08:59:27 -07003029 if (bootTrustedModuleRequired)
3030 {
3031 setTrustedModuleRequiredToBoot(asyncResp,
3032 *bootTrustedModuleRequired);
3033 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003034
Ed Tanous002d39b2022-05-31 08:59:27 -07003035 if (locationIndicatorActive)
3036 {
3037 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3038 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039
Ed Tanous002d39b2022-05-31 08:59:27 -07003040 // TODO (Gunnar): Remove IndicatorLED after enough time has
3041 // passed
3042 if (indicatorLed)
3043 {
3044 setIndicatorLedState(asyncResp, *indicatorLed);
3045 asyncResp->res.addHeader(boost::beast::http::field::warning,
3046 "299 - \"IndicatorLED is deprecated. Use "
3047 "LocationIndicatorActive instead.\"");
3048 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003049
Ed Tanous002d39b2022-05-31 08:59:27 -07003050 if (powerRestorePolicy)
3051 {
3052 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3053 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003054
Ed Tanous002d39b2022-05-31 08:59:27 -07003055 if (powerMode)
3056 {
3057 setPowerMode(asyncResp, *powerMode);
3058 }
Chris Cain37bbf982021-09-20 10:53:09 -05003059
Ed Tanous002d39b2022-05-31 08:59:27 -07003060 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3061 ipsExitTime)
3062 {
3063 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3064 ipsExitUtil, ipsExitTime);
3065 }
3066 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003067}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303068
3069/**
3070 * SystemResetActionInfo derived class for delivering Computer Systems
3071 * ResetType AllowableValues using ResetInfo schema.
3072 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003073inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303074{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303075 /**
3076 * Functions triggers appropriate requests on DBus
3077 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003078 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003079 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003080 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003081 [&app](const crow::Request& req,
3082 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003083 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003084 {
3085 return;
3086 }
Ed Tanous14766872022-03-15 10:44:42 -07003087
Ed Tanous002d39b2022-05-31 08:59:27 -07003088 asyncResp->res.jsonValue["@odata.id"] =
3089 "/redfish/v1/Systems/system/ResetActionInfo";
3090 asyncResp->res.jsonValue["@odata.type"] =
3091 "#ActionInfo.v1_1_2.ActionInfo";
3092 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3093 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003094
3095 nlohmann::json::array_t parameters;
3096 nlohmann::json::object_t parameter;
3097
3098 parameter["Name"] = "ResetType";
3099 parameter["Required"] = true;
3100 parameter["DataType"] = "String";
3101 nlohmann::json::array_t allowableValues;
3102 allowableValues.emplace_back("On");
3103 allowableValues.emplace_back("ForceOff");
3104 allowableValues.emplace_back("ForceOn");
3105 allowableValues.emplace_back("ForceRestart");
3106 allowableValues.emplace_back("GracefulRestart");
3107 allowableValues.emplace_back("GracefulShutdown");
3108 allowableValues.emplace_back("PowerCycle");
3109 allowableValues.emplace_back("Nmi");
3110 parameter["AllowableValues"] = std::move(allowableValues);
3111 parameters.emplace_back(std::move(parameter));
3112
3113 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003114 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003115}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003116} // namespace redfish