blob: ca85098e4a30a06d4e5d08e8cf10745ed88f9824 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
23
John Edward Broadbent7e860f12021-04-08 15:57:16 -070024#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070025#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080026#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070027#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070028#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060029#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050031
Ed Tanousabf2add2019-01-22 16:40:12 -080032#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034namespace redfish
35{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020036
Alpana Kumari9d3ae102019-04-12 06:49:32 -050037/**
38 * @brief Updates the Functional State of DIMMs
39 *
40 * @param[in] aResp Shared pointer for completing asynchronous calls
41 * @param[in] dimmState Dimm's Functional state, true/false
42 *
43 * @return None.
44 */
zhanghch058d1b46d2021-04-01 11:18:24 +080045inline void
46 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070047 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070049 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050
Gunnar Mills4e0453b2020-07-08 14:00:30 -050051 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052 // Update STATE only if previous State was DISABLED and current Dimm is
53 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050054 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
56 if (prevMemSummary == "Disabled")
57 {
Ed Tanouse05aec52022-01-25 10:28:56 -080058 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 {
60 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
61 "Enabled";
62 }
63 }
64}
65
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050066/*
67 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
68 *
69 * @param[in] aResp Shared pointer for completing asynchronous calls
70 * @param[in] cpuPresenceState CPU present or not
71 *
72 * @return None.
73 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074inline void
75 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
76 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070078 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079
Ed Tanous55f79e62022-01-25 11:26:16 -080080 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050082 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080083 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080084 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050085 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080086 if (procCountPtr != nullptr)
87 {
88 // shouldn't be possible to be nullptr
89 *procCountPtr += 1;
90 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092}
93
94/*
95 * @brief Update "ProcessorSummary" "Status" "State" based on
96 * CPU Functional State
97 *
98 * @param[in] aResp Shared pointer for completing asynchronous calls
99 * @param[in] cpuFunctionalState is CPU functional true/false
100 *
101 * @return None.
102 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700103inline void
104 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
105 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700107 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
111
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500112 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113 // Update STATE only if previous State was Non_Functional and current CPU is
114 // Functional.
115 if (prevProcState == "Disabled")
116 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800117 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 {
119 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
120 "Enabled";
121 }
122 }
123}
124
Ali Ahmed03fbed92021-09-03 02:33:43 -0500125inline void getProcessorProperties(
126 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
127 const std::string& path,
Ed Tanous168e20c2021-12-13 14:39:53 -0800128 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
Ali Ahmed03fbed92021-09-03 02:33:43 -0500129 properties)
130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
Ed Tanouse662eae2022-01-25 10:39:19 -0800179 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500180 {
181 messages::internalError(aResp->res);
182 return;
183 }
184
185 nlohmann::json& coreCount =
186 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
187 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
188
189 if (coreCountPtr == nullptr)
190 {
191 coreCount = 0;
192 }
193 else
194 {
195 *coreCountPtr += *coreCountVal;
196 }
197 }
198 }
199}
200
201/*
202 * @brief Get ProcessorSummary fields
203 *
204 * @param[in] aResp Shared pointer for completing asynchronous calls
205 * @param[in] service dbus service for Cpu Information
206 * @param[in] path dbus path for Cpu
207 *
208 * @return None.
209 */
210inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 const std::string& service,
212 const std::string& path)
213{
214
215 crow::connections::systemBus->async_method_call(
216 [aResp, service,
217 path](const boost::system::error_code ec2,
218 const std::vector<std::pair<
Ed Tanous168e20c2021-12-13 14:39:53 -0800219 std::string, dbus::utility::DbusVariantType>>& properties) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500220 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);
227 },
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(
James Feist5bc2dc82019-10-22 14:33:16 -0700247 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700248 const boost::system::error_code ec,
249 const std::vector<std::pair<
250 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500251 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
252 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700253 if (ec)
254 {
255 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700256 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700257 return;
258 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700259 // Iterate over all retrieved ObjectPaths.
260 for (const std::pair<std::string,
261 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500262 std::string, std::vector<std::string>>>>&
263 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700264 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500265 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 BMCWEB_LOG_DEBUG << "Got path: " << path;
267 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500268 std::pair<std::string, std::vector<std::string>>>&
269 connectionNames = object.second;
Ed Tanous26f69762022-01-25 09:49:11 -0800270 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700271 {
272 continue;
273 }
Ed Tanous029573d2019-02-01 10:57:49 -0800274
James Feist5bc2dc82019-10-22 14:33:16 -0700275 auto memoryHealth = std::make_shared<HealthPopulate>(
276 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
277
278 auto cpuHealth = std::make_shared<HealthPopulate>(
279 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
280
281 systemHealth->children.emplace_back(memoryHealth);
282 systemHealth->children.emplace_back(cpuHealth);
283
Ed Tanous029573d2019-02-01 10:57:49 -0800284 // This is not system, so check if it's cpu, dimm, UUID or
285 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500286 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700287 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500288 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700289 {
Ed Tanous029573d2019-02-01 10:57:49 -0800290 if (interfaceName ==
291 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700292 {
Ed Tanous029573d2019-02-01 10:57:49 -0800293 BMCWEB_LOG_DEBUG
294 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500295
Ed Tanous029573d2019-02-01 10:57:49 -0800296 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500297 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700298 path](const boost::system::error_code ec2,
Ed Tanous168e20c2021-12-13 14:39:53 -0800299 const std::vector<std::pair<
300 std::string,
301 dbus::utility::DbusVariantType>>&
Ed Tanousf23b7292020-10-15 09:41:17 -0700302 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000303 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800304 {
305 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000306 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800307 messages::internalError(aResp->res);
308 return;
309 }
310 BMCWEB_LOG_DEBUG << "Got "
311 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500312 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500313
Ed Tanous26f69762022-01-25 09:49:11 -0800314 if (!properties.empty())
Ed Tanous029573d2019-02-01 10:57:49 -0800315 {
Ed Tanous168e20c2021-12-13 14:39:53 -0800316 for (const std::pair<
317 std::string,
318 dbus::utility::
319 DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700321 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800322 if (property.first !=
323 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700324 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800325 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700326 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500327 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500328 std::get_if<uint32_t>(
329 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800330 if (value == nullptr)
331 {
332 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800333 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800334 continue;
335 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500336 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800337 aResp->res.jsonValue
338 ["MemorySummary"]
339 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500340 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800341 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500342 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800343 if (preValue == nullptr)
344 {
345 continue;
346 }
George Liu0fda0f12021-11-16 10:06:17 +0800347 aResp->res.jsonValue
348 ["MemorySummary"]
349 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800350 *value / (1024 * 1024) +
351 *preValue;
352 aResp->res
353 .jsonValue["MemorySummary"]
354 ["Status"]["State"] =
355 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700356 }
Ed Tanous029573d2019-02-01 10:57:49 -0800357 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500358 else
359 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700360 sdbusplus::asio::getProperty<bool>(
361 *crow::connections::systemBus,
362 service, path,
363 "xyz.openbmc_project.State."
364 "Decorator.OperationalStatus",
365 "Functional",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500366 [aResp](
367 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000368 ec3,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700369 bool dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000370 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500371 {
372 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800373 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000374 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500375 return;
376 }
377 updateDimmProperties(aResp,
378 dimmState);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700379 });
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500380 }
Ed Tanous029573d2019-02-01 10:57:49 -0800381 },
382 connection.first, path,
383 "org.freedesktop.DBus.Properties", "GetAll",
384 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700385
386 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800387 }
388 else if (interfaceName ==
389 "xyz.openbmc_project.Inventory.Item.Cpu")
390 {
391 BMCWEB_LOG_DEBUG
392 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500393
Ali Ahmed03fbed92021-09-03 02:33:43 -0500394 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700395
396 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800397 }
398 else if (interfaceName ==
399 "xyz.openbmc_project.Common.UUID")
400 {
401 BMCWEB_LOG_DEBUG
402 << "Found UUID, now get its properties.";
403 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800404 [aResp](const boost::system::error_code ec3,
405 const std::vector<std::pair<
406 std::string,
407 dbus::utility::DbusVariantType>>&
408 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000409 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800410 {
411 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000412 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800413 messages::internalError(aResp->res);
414 return;
415 }
416 BMCWEB_LOG_DEBUG << "Got "
417 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500418 << " UUID properties.";
Ed Tanous168e20c2021-12-13 14:39:53 -0800419 for (const std::pair<
420 std::string,
421 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500422 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800423 {
Ed Tanous029573d2019-02-01 10:57:49 -0800424 if (property.first == "UUID")
425 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500426 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500427 std::get_if<std::string>(
428 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700429
Ed Tanous029573d2019-02-01 10:57:49 -0800430 if (value != nullptr)
431 {
432 std::string valueStr = *value;
433 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700434 {
Ed Tanous029573d2019-02-01 10:57:49 -0800435 valueStr.insert(8, 1, '-');
436 valueStr.insert(13, 1, '-');
437 valueStr.insert(18, 1, '-');
438 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700439 }
Ed Tanous029573d2019-02-01 10:57:49 -0800440 BMCWEB_LOG_DEBUG << "UUID = "
441 << valueStr;
442 aResp->res.jsonValue["UUID"] =
443 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700444 }
445 }
Ed Tanous029573d2019-02-01 10:57:49 -0800446 }
447 },
448 connection.first, path,
449 "org.freedesktop.DBus.Properties", "GetAll",
450 "xyz.openbmc_project.Common.UUID");
451 }
452 else if (interfaceName ==
453 "xyz.openbmc_project.Inventory.Item.System")
454 {
455 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800456 [aResp](const boost::system::error_code ec2,
457 const std::vector<std::pair<
458 std::string,
459 dbus::utility::DbusVariantType>>&
460 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000461 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800462 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700463 // doesn't have to include this
464 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800465 return;
466 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500467 BMCWEB_LOG_DEBUG
468 << "Got " << propertiesList.size()
469 << " properties for system";
Ed Tanous168e20c2021-12-13 14:39:53 -0800470 for (const std::pair<
471 std::string,
472 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500473 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800474 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500475 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600476 property.first;
477 if ((propertyName == "PartNumber") ||
478 (propertyName == "SerialNumber") ||
479 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500480 (propertyName == "Model") ||
481 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800482 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500483 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600484 std::get_if<std::string>(
485 &property.second);
486 if (value != nullptr)
487 {
488 aResp->res
489 .jsonValue[propertyName] =
490 *value;
491 }
Ed Tanous029573d2019-02-01 10:57:49 -0800492 }
493 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500494
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600495 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500496 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600497 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500498 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800499 },
500 connection.first, path,
501 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800502 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700503
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700504 sdbusplus::asio::getProperty<std::string>(
505 *crow::connections::systemBus, connection.first,
506 path,
507 "xyz.openbmc_project.Inventory.Decorator."
508 "AssetTag",
509 "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -0800510 [aResp](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700511 const std::string& value) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000512 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700513 {
514 // doesn't have to include this
515 // interface
516 return;
517 }
518
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700519 aResp->res.jsonValue["AssetTag"] = value;
520 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700521 }
522 }
523 }
524 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700525 },
526 "xyz.openbmc_project.ObjectMapper",
527 "/xyz/openbmc_project/object_mapper",
528 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700529 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500530 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700531 "xyz.openbmc_project.Inventory.Decorator.Asset",
532 "xyz.openbmc_project.Inventory.Item.Cpu",
533 "xyz.openbmc_project.Inventory.Item.Dimm",
534 "xyz.openbmc_project.Inventory.Item.System",
535 "xyz.openbmc_project.Common.UUID",
536 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700537}
538
539/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 * @brief Retrieves host state properties over dbus
541 *
542 * @param[in] aResp Shared pointer for completing asynchronous calls.
543 *
544 * @return None.
545 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800546inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700547{
548 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700549 sdbusplus::asio::getProperty<std::string>(
550 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
551 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
552 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800553 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700554 const std::string& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700555 if (ec)
556 {
Andrew Geissler22228c22022-01-31 13:55:33 -0600557 if (ec == boost::system::errc::host_unreachable)
558 {
559 // Service not available, no error, just don't return
560 // host state info
561 BMCWEB_LOG_DEBUG << "Service not available " << ec;
562 return;
563 }
564 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700565 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 return;
567 }
Ed Tanous66173382018-08-15 18:20:59 -0700568
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700569 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
570 // Verify Host State
571 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700572 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700573 aResp->res.jsonValue["PowerState"] = "On";
574 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700575 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700576 else if (hostState ==
577 "xyz.openbmc_project.State.Host.HostState.Quiesced")
578 {
579 aResp->res.jsonValue["PowerState"] = "On";
580 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
581 }
582 else if (hostState ==
583 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
584 {
585 aResp->res.jsonValue["PowerState"] = "On";
586 aResp->res.jsonValue["Status"]["State"] = "InTest";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOn";
593 aResp->res.jsonValue["Status"]["State"] = "Starting";
594 }
595 else if (
596 hostState ==
597 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
598 {
599 aResp->res.jsonValue["PowerState"] = "PoweringOff";
600 aResp->res.jsonValue["Status"]["State"] = "Disabled";
601 }
602 else
603 {
604 aResp->res.jsonValue["PowerState"] = "Off";
605 aResp->res.jsonValue["Status"]["State"] = "Disabled";
606 }
607 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700608}
609
610/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500611 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530612 *
613 * @param[in] dbusSource The boot source in DBUS speak.
614 *
615 * @return Returns as a string, the boot source in Redfish terms. If translation
616 * cannot be done, returns an empty string.
617 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000618inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530619{
620 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
621 {
622 return "None";
623 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700624 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530625 {
626 return "Hdd";
627 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700628 if (dbusSource ==
629 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 {
631 return "Cd";
632 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700633 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530634 {
635 return "Pxe";
636 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700637 if (dbusSource ==
638 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700639 {
640 return "Usb";
641 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700642 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530643}
644
645/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300646 * @brief Translates boot type DBUS property value to redfish.
647 *
648 * @param[in] dbusType The boot type in DBUS speak.
649 *
650 * @return Returns as a string, the boot type in Redfish terms. If translation
651 * cannot be done, returns an empty string.
652 */
653inline std::string dbusToRfBootType(const std::string& dbusType)
654{
655 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
656 {
657 return "Legacy";
658 }
659 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
660 {
661 return "UEFI";
662 }
663 return "";
664}
665
666/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500667 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668 *
669 * @param[in] dbusMode The boot mode in DBUS speak.
670 *
671 * @return Returns as a string, the boot mode in Redfish terms. If translation
672 * cannot be done, returns an empty string.
673 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000674inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530675{
676 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
677 {
678 return "None";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "Diags";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685 {
686 return "BiosSetup";
687 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700688 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530689}
690
691/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600692 * @brief Translates boot progress DBUS property value to redfish.
693 *
694 * @param[in] dbusBootProgress The boot progress in DBUS speak.
695 *
696 * @return Returns as a string, the boot progress in Redfish terms. If
697 * translation cannot be done, returns "None".
698 */
699inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
700{
701 // Now convert the D-Bus BootProgress to the appropriate Redfish
702 // enum
703 std::string rfBpLastState = "None";
704 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
705 "ProgressStages.Unspecified")
706 {
707 rfBpLastState = "None";
708 }
709 else if (dbusBootProgress ==
710 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
711 "PrimaryProcInit")
712 {
713 rfBpLastState = "PrimaryProcessorInitializationStarted";
714 }
715 else if (dbusBootProgress ==
716 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
717 "BusInit")
718 {
719 rfBpLastState = "BusInitializationStarted";
720 }
721 else if (dbusBootProgress ==
722 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
723 "MemoryInit")
724 {
725 rfBpLastState = "MemoryInitializationStarted";
726 }
727 else if (dbusBootProgress ==
728 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
729 "SecondaryProcInit")
730 {
731 rfBpLastState = "SecondaryProcessorInitializationStarted";
732 }
733 else if (dbusBootProgress ==
734 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
735 "PCIInit")
736 {
737 rfBpLastState = "PCIResourceConfigStarted";
738 }
739 else if (dbusBootProgress ==
740 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
741 "SystemSetup")
742 {
743 rfBpLastState = "SetupEntered";
744 }
745 else if (dbusBootProgress ==
746 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
747 "SystemInitComplete")
748 {
749 rfBpLastState = "SystemHardwareInitializationComplete";
750 }
751 else if (dbusBootProgress ==
752 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
753 "OSStart")
754 {
755 rfBpLastState = "OSBootStarted";
756 }
757 else if (dbusBootProgress ==
758 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
759 "OSRunning")
760 {
761 rfBpLastState = "OSRunning";
762 }
763 else
764 {
765 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
766 << dbusBootProgress;
767 // Just return the default
768 }
769 return rfBpLastState;
770}
771
772/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500773 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 *
775 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 * @param[out] bootSource The DBus source
777 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800781inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500782 const std::string& rfSource,
783 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300785 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
786 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788 if (rfSource == "None")
789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700792 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530793 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
795 }
796 else if (rfSource == "Hdd")
797 {
798 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
799 }
800 else if (rfSource == "Diags")
801 {
802 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
803 }
804 else if (rfSource == "Cd")
805 {
806 bootSource =
807 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
808 }
809 else if (rfSource == "BiosSetup")
810 {
811 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530812 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 else if (rfSource == "Usb")
814 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700815 bootSource =
816 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700817 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818 else
819 {
George Liu0fda0f12021-11-16 10:06:17 +0800820 BMCWEB_LOG_DEBUG
821 << "Invalid property value for BootSourceOverrideTarget: "
822 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 messages::propertyValueNotInList(aResp->res, rfSource,
824 "BootSourceTargetOverride");
825 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530826 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700827 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828}
Ali Ahmed19817712021-06-29 17:01:52 -0500829
Andrew Geissler978b8802020-11-19 13:36:40 -0600830/**
831 * @brief Retrieves boot progress of the system
832 *
833 * @param[in] aResp Shared pointer for generating response message.
834 *
835 * @return None.
836 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800837inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600838{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700839 sdbusplus::asio::getProperty<std::string>(
840 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
841 "/xyz/openbmc_project/state/host0",
842 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600843 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700844 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600845 if (ec)
846 {
847 // BootProgress is an optional object so just do nothing if
848 // not found
849 return;
850 }
851
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700852 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600853
Andrew Geisslere43914b2022-01-06 13:59:39 -0600854 aResp->res.jsonValue["BootProgress"]["LastState"] =
855 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700856 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600857}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530858
859/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300860 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300861 *
862 * @param[in] aResp Shared pointer for generating response message.
863 *
864 * @return None.
865 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300867inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700869 sdbusplus::asio::getProperty<std::string>(
870 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
871 "/xyz/openbmc_project/control/host0/boot",
872 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300873 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700874 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300875 if (ec)
876 {
877 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300878 return;
879 }
880
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700881 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882
George Liu0fda0f12021-11-16 10:06:17 +0800883 aResp->res
884 .jsonValue["Boot"]
885 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
886 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300887
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700888 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300889 if (rfType.empty())
890 {
891 messages::internalError(aResp->res);
892 return;
893 }
894
895 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700896 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300897}
898
899/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300900 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530901 *
902 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530903 *
904 * @return None.
905 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300906
907inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700909 sdbusplus::asio::getProperty<std::string>(
910 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
911 "/xyz/openbmc_project/control/host0/boot",
912 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300913 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700914 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 if (ec)
916 {
917 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
918 messages::internalError(aResp->res);
919 return;
920 }
921
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700922 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923
George Liu0fda0f12021-11-16 10:06:17 +0800924 aResp->res
925 .jsonValue["Boot"]
926 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
927 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530928
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700929 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530930 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
931 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700932 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933 if (!rfMode.empty())
934 {
935 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
936 rfMode;
937 }
938 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700939 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940}
941
942/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
945 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530946 *
947 * @return None.
948 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300949
950inline void
951 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530952{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700953 sdbusplus::asio::getProperty<std::string>(
954 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
955 "/xyz/openbmc_project/control/host0/boot",
956 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300957 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700958 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 if (ec)
960 {
961 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
962 messages::internalError(aResp->res);
963 return;
964 }
965
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700966 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700968 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969 if (!rfSource.empty())
970 {
971 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
972 rfSource;
973 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300974
975 // Get BootMode as BootSourceOverrideTarget is constructed
976 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300977 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700978 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530979}
980
981/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300982 * @brief This functions abstracts all the logic behind getting a
983 * "BootSourceOverrideEnabled" property from an overall boot override enable
984 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985 *
986 * @param[in] aResp Shared pointer for generating response message.
987 *
988 * @return None.
989 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300991inline void
992 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
993 const bool bootOverrideEnableSetting)
994{
995 if (!bootOverrideEnableSetting)
996 {
997 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
998 return;
999 }
1000
1001 // If boot source override is enabled, we need to check 'one_time'
1002 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001003 sdbusplus::asio::getProperty<bool>(
1004 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1005 "/xyz/openbmc_project/control/host0/boot/one_time",
1006 "xyz.openbmc_project.Object.Enable", "Enabled",
1007 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008 if (ec)
1009 {
1010 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001011 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301012 return;
1013 }
1014
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001015 if (oneTimeSetting)
1016 {
1017 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1018 "Once";
1019 }
1020 else
1021 {
1022 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1023 "Continuous";
1024 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001025 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026}
1027
1028/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029 * @brief Retrieves boot override enable over DBUS
1030 *
1031 * @param[in] aResp Shared pointer for generating response message.
1032 *
1033 * @return None.
1034 */
1035
1036inline void
1037 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1038{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001039 sdbusplus::asio::getProperty<bool>(
1040 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1041 "/xyz/openbmc_project/control/host0/boot",
1042 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001044 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001045 if (ec)
1046 {
1047 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1048 messages::internalError(aResp->res);
1049 return;
1050 }
1051
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001052 processBootOverrideEnable(aResp, bootOverrideEnable);
1053 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001054}
1055
1056/**
1057 * @brief Retrieves boot source override properties
1058 *
1059 * @param[in] aResp Shared pointer for generating response message.
1060 *
1061 * @return None.
1062 */
1063inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1064{
1065 BMCWEB_LOG_DEBUG << "Get boot information.";
1066
1067 getBootOverrideSource(aResp);
1068 getBootOverrideType(aResp);
1069 getBootOverrideEnable(aResp);
1070}
1071
1072/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001073 * @brief Retrieves the Last Reset Time
1074 *
1075 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1076 * and power off. Even though this is the "system" Redfish object look at the
1077 * chassis D-Bus interface for the LastStateChangeTime since this has the
1078 * last power operation time.
1079 *
1080 * @param[in] aResp Shared pointer for generating response message.
1081 *
1082 * @return None.
1083 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001084inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001085{
1086 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1087
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001088 sdbusplus::asio::getProperty<uint64_t>(
1089 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1090 "/xyz/openbmc_project/state/chassis0",
1091 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1092 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001093 if (ec)
1094 {
1095 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1096 return;
1097 }
1098
Gunnar Millsc0557e12020-06-30 11:26:20 -05001099 // LastStateChangeTime is epoch time, in milliseconds
1100 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001101 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001102
1103 // Convert to ISO 8601 standard
1104 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001105 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001106 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001107}
1108
1109/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001110 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1111 *
1112 * @param[in] aResp Shared pointer for generating response message.
1113 *
1114 * @return None.
1115 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001116inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001117{
1118 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1119
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001120 sdbusplus::asio::getProperty<bool>(
1121 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1122 "/xyz/openbmc_project/control/host0/auto_reboot",
1123 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1124 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001125 if (ec)
1126 {
1127 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1128 return;
1129 }
1130
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001131 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
Ed Tanouse05aec52022-01-25 10:28:56 -08001132 if (autoRebootEnabled)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001133 {
1134 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1135 "RetryAttempts";
1136 // If AutomaticRetry (AutoReboot) is enabled see how many
1137 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001138 sdbusplus::asio::getProperty<uint32_t>(
1139 *crow::connections::systemBus,
1140 "xyz.openbmc_project.State.Host",
1141 "/xyz/openbmc_project/state/host0",
1142 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1143 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001144 [aResp](const boost::system::error_code ec2,
Ed Tanous914e2d52022-01-07 11:38:34 -08001145 const uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001146 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001147 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001148 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001149 return;
1150 }
1151
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001152 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001153 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001154
1155 aResp->res
1156 .jsonValue["Boot"]
1157 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001158 autoRebootAttemptsLeft;
1159 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001160 }
1161 else
1162 {
1163 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1164 "Disabled";
1165 }
1166
1167 // Not on D-Bus. Hardcoded here:
1168 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1169 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001170
1171 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1172 // and RetryAttempts. OpenBMC only supports Disabled and
1173 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001174 aResp->res
1175 .jsonValue["Boot"]
1176 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1177 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001178 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001179}
1180
1181/**
George Liuc6a620f2020-04-10 17:18:11 +08001182 * @brief Retrieves power restore policy over DBUS.
1183 *
1184 * @param[in] aResp Shared pointer for generating response message.
1185 *
1186 * @return None.
1187 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001188inline void
1189 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001190{
1191 BMCWEB_LOG_DEBUG << "Get power restore policy";
1192
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001193 sdbusplus::asio::getProperty<std::string>(
1194 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1195 "/xyz/openbmc_project/control/host0/power_restore_policy",
1196 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1197 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001198 if (ec)
1199 {
1200 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1201 return;
1202 }
1203
George Liu0fda0f12021-11-16 10:06:17 +08001204 const boost::container::flat_map<std::string, std::string> policyMaps = {
1205 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1206 "AlwaysOn"},
1207 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1208 "AlwaysOff"},
1209 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
Matthew Barth4ed47cb2022-03-03 15:58:06 -06001210 "LastState"},
1211 // Return `AlwaysOff` when power restore policy set to "None"
1212 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1213 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001214
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001215 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001216 if (policyMapsIt == policyMaps.end())
1217 {
1218 messages::internalError(aResp->res);
1219 return;
1220 }
1221
1222 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001223 });
George Liuc6a620f2020-04-10 17:18:11 +08001224}
1225
1226/**
Ali Ahmed19817712021-06-29 17:01:52 -05001227 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1228 * TPM is required for booting the host.
1229 *
1230 * @param[in] aResp Shared pointer for generating response message.
1231 *
1232 * @return None.
1233 */
1234inline void getTrustedModuleRequiredToBoot(
1235 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1236{
1237 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1238
1239 crow::connections::systemBus->async_method_call(
1240 [aResp](
1241 const boost::system::error_code ec,
1242 std::vector<std::pair<
1243 std::string,
1244 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1245 subtree) {
1246 if (ec)
1247 {
1248 BMCWEB_LOG_DEBUG
1249 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1250 // This is an optional D-Bus object so just return if
1251 // error occurs
1252 return;
1253 }
Ed Tanous26f69762022-01-25 09:49:11 -08001254 if (subtree.empty())
Ali Ahmed19817712021-06-29 17:01:52 -05001255 {
1256 // As noted above, this is an optional interface so just return
1257 // if there is no instance found
1258 return;
1259 }
1260
1261 /* When there is more than one TPMEnable object... */
1262 if (subtree.size() > 1)
1263 {
1264 BMCWEB_LOG_DEBUG
1265 << "DBUS response has more than 1 TPM Enable object:"
1266 << subtree.size();
1267 // Throw an internal Error and return
1268 messages::internalError(aResp->res);
1269 return;
1270 }
1271
1272 // Make sure the Dbus response map has a service and objectPath
1273 // field
1274 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1275 {
1276 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1277 messages::internalError(aResp->res);
1278 return;
1279 }
1280
1281 const std::string& path = subtree[0].first;
1282 const std::string& serv = subtree[0].second.begin()->first;
1283
1284 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001285 sdbusplus::asio::getProperty<bool>(
1286 *crow::connections::systemBus, serv, path,
1287 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1288 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001289 if (ec)
1290 {
1291 BMCWEB_LOG_DEBUG
1292 << "D-BUS response error on TPM.Policy Get" << ec;
1293 messages::internalError(aResp->res);
1294 return;
1295 }
1296
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001297 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001298 {
1299 aResp->res
1300 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1301 "Required";
1302 }
1303 else
1304 {
1305 aResp->res
1306 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1307 "Disabled";
1308 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001309 });
Ali Ahmed19817712021-06-29 17:01:52 -05001310 },
1311 "xyz.openbmc_project.ObjectMapper",
1312 "/xyz/openbmc_project/object_mapper",
1313 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1314 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1315}
1316
1317/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001318 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1319 * TPM is required for booting the host.
1320 *
1321 * @param[in] aResp Shared pointer for generating response message.
1322 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1323 *
1324 * @return None.
1325 */
1326inline void setTrustedModuleRequiredToBoot(
1327 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1328{
1329 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1330
1331 crow::connections::systemBus->async_method_call(
1332 [aResp, tpmRequired](
1333 const boost::system::error_code ec,
1334 std::vector<std::pair<
1335 std::string,
1336 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1337 subtree) {
1338 if (ec)
1339 {
1340 BMCWEB_LOG_DEBUG
1341 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1342 messages::internalError(aResp->res);
1343 return;
1344 }
Ed Tanous26f69762022-01-25 09:49:11 -08001345 if (subtree.empty())
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001346 {
1347 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1348 "TrustedModuleRequiredToBoot");
1349 return;
1350 }
1351
1352 /* When there is more than one TPMEnable object... */
1353 if (subtree.size() > 1)
1354 {
1355 BMCWEB_LOG_DEBUG
1356 << "DBUS response has more than 1 TPM Enable object:"
1357 << subtree.size();
1358 // Throw an internal Error and return
1359 messages::internalError(aResp->res);
1360 return;
1361 }
1362
1363 // Make sure the Dbus response map has a service and objectPath
1364 // field
1365 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1366 {
1367 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1368 messages::internalError(aResp->res);
1369 return;
1370 }
1371
1372 const std::string& path = subtree[0].first;
1373 const std::string& serv = subtree[0].second.begin()->first;
1374
1375 if (serv.empty())
1376 {
1377 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1378 messages::internalError(aResp->res);
1379 return;
1380 }
1381
1382 // Valid TPM Enable object found, now setting the value
1383 crow::connections::systemBus->async_method_call(
1384 [aResp](const boost::system::error_code ec) {
1385 if (ec)
1386 {
George Liu0fda0f12021-11-16 10:06:17 +08001387 BMCWEB_LOG_DEBUG
1388 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1389 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001390 messages::internalError(aResp->res);
1391 return;
1392 }
1393 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1394 },
1395 serv, path, "org.freedesktop.DBus.Properties", "Set",
1396 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001397 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001398 },
1399 "xyz.openbmc_project.ObjectMapper",
1400 "/xyz/openbmc_project/object_mapper",
1401 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1402 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1403}
1404
1405/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301406 * @brief Sets boot properties into DBUS object(s).
1407 *
1408 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001409 * @param[in] bootType The boot type to set.
1410 * @return Integer error code.
1411 */
1412inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001413 const std::optional<std::string>& bootType)
1414{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001415 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001416
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001417 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001418 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001419 return;
1420 }
1421
1422 // Source target specified
1423 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1424 // Figure out which DBUS interface and property to use
1425 if (*bootType == "Legacy")
1426 {
1427 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1428 }
1429 else if (*bootType == "UEFI")
1430 {
1431 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1432 }
1433 else
1434 {
1435 BMCWEB_LOG_DEBUG << "Invalid property value for "
1436 "BootSourceOverrideMode: "
1437 << *bootType;
1438 messages::propertyValueNotInList(aResp->res, *bootType,
1439 "BootSourceOverrideMode");
1440 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001441 }
1442
1443 // Act on validated parameters
1444 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1445
1446 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001447 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001448 if (ec)
1449 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001450 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1451 if (ec.value() == boost::asio::error::host_unreachable)
1452 {
1453 messages::resourceNotFound(aResp->res, "Set", "BootType");
1454 return;
1455 }
1456 messages::internalError(aResp->res);
1457 return;
1458 }
1459 BMCWEB_LOG_DEBUG << "Boot type update done.";
1460 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001461 "xyz.openbmc_project.Settings",
1462 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001463 "org.freedesktop.DBus.Properties", "Set",
1464 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001465 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001466}
1467
1468/**
1469 * @brief Sets boot properties into DBUS object(s).
1470 *
1471 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001472 * @param[in] bootType The boot type to set.
1473 * @return Integer error code.
1474 */
1475inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1476 const std::optional<std::string>& bootEnable)
1477{
1478 if (!bootEnable)
1479 {
1480 return;
1481 }
1482 // Source target specified
1483 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1484
1485 bool bootOverrideEnable = false;
1486 bool bootOverridePersistent = false;
1487 // Figure out which DBUS interface and property to use
1488 if (*bootEnable == "Disabled")
1489 {
1490 bootOverrideEnable = false;
1491 }
1492 else if (*bootEnable == "Once")
1493 {
1494 bootOverrideEnable = true;
1495 bootOverridePersistent = false;
1496 }
1497 else if (*bootEnable == "Continuous")
1498 {
1499 bootOverrideEnable = true;
1500 bootOverridePersistent = true;
1501 }
1502 else
1503 {
George Liu0fda0f12021-11-16 10:06:17 +08001504 BMCWEB_LOG_DEBUG
1505 << "Invalid property value for BootSourceOverrideEnabled: "
1506 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001507 messages::propertyValueNotInList(aResp->res, *bootEnable,
1508 "BootSourceOverrideEnabled");
1509 return;
1510 }
1511
1512 // Act on validated parameters
1513 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1514
1515 crow::connections::systemBus->async_method_call(
1516 [aResp](const boost::system::error_code ec) {
1517 if (ec)
1518 {
1519 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1520 messages::internalError(aResp->res);
1521 return;
1522 }
1523 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1524 },
1525 "xyz.openbmc_project.Settings",
1526 "/xyz/openbmc_project/control/host0/boot",
1527 "org.freedesktop.DBus.Properties", "Set",
1528 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001529 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001530
1531 if (!bootOverrideEnable)
1532 {
1533 return;
1534 }
1535
1536 // In case boot override is enabled we need to set correct value for the
1537 // 'one_time' enable DBus interface
1538 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1539 << bootOverridePersistent;
1540
1541 crow::connections::systemBus->async_method_call(
1542 [aResp](const boost::system::error_code ec) {
1543 if (ec)
1544 {
1545 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1546 messages::internalError(aResp->res);
1547 return;
1548 }
1549 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1550 },
1551 "xyz.openbmc_project.Settings",
1552 "/xyz/openbmc_project/control/host0/boot/one_time",
1553 "org.freedesktop.DBus.Properties", "Set",
1554 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001555 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001556}
1557
1558/**
1559 * @brief Sets boot properties into DBUS object(s).
1560 *
1561 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301562 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301563 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001564 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301565 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001566inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001567 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301568{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001569 std::string bootSourceStr;
1570 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001571
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001572 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301573 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001574 return;
1575 }
1576
1577 // Source target specified
1578 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1579 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001580 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1581 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001582 {
1583 BMCWEB_LOG_DEBUG
1584 << "Invalid property value for BootSourceOverrideTarget: "
1585 << *bootSource;
1586 messages::propertyValueNotInList(aResp->res, *bootSource,
1587 "BootSourceTargetOverride");
1588 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001589 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301590
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001591 // Act on validated parameters
1592 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1593 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001594
1595 crow::connections::systemBus->async_method_call(
1596 [aResp](const boost::system::error_code ec) {
1597 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301598 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001599 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1600 messages::internalError(aResp->res);
1601 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301602 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001603 BMCWEB_LOG_DEBUG << "Boot source update done.";
1604 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001605 "xyz.openbmc_project.Settings",
1606 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001607 "org.freedesktop.DBus.Properties", "Set",
1608 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001609 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001610
1611 crow::connections::systemBus->async_method_call(
1612 [aResp](const boost::system::error_code ec) {
1613 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301614 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001615 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1616 messages::internalError(aResp->res);
1617 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301618 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001619 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1620 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001621 "xyz.openbmc_project.Settings",
1622 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001623 "org.freedesktop.DBus.Properties", "Set",
1624 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001625 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001626}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001627
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001628/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001629 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301630 *
1631 * @param[in] aResp Shared pointer for generating response message.
1632 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001633 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301634 * @param[in] bootEnable The boot override enable from incoming RF request.
1635 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001636 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301637 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001638
1639inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1640 const std::optional<std::string>& bootSource,
1641 const std::optional<std::string>& bootType,
1642 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301643{
1644 BMCWEB_LOG_DEBUG << "Set boot information.";
1645
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001646 setBootModeOrSource(aResp, bootSource);
1647 setBootType(aResp, bootType);
1648 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301649}
1650
George Liuc6a620f2020-04-10 17:18:11 +08001651/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001652 * @brief Sets AssetTag
1653 *
1654 * @param[in] aResp Shared pointer for generating response message.
1655 * @param[in] assetTag "AssetTag" from request.
1656 *
1657 * @return None.
1658 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001659inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001660 const std::string& assetTag)
1661{
1662 crow::connections::systemBus->async_method_call(
1663 [aResp, assetTag](
1664 const boost::system::error_code ec,
1665 const std::vector<std::pair<
1666 std::string,
1667 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1668 subtree) {
1669 if (ec)
1670 {
1671 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1672 messages::internalError(aResp->res);
1673 return;
1674 }
Ed Tanous26f69762022-01-25 09:49:11 -08001675 if (subtree.empty())
Gunnar Mills98e386e2020-10-30 14:58:09 -05001676 {
1677 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1678 messages::internalError(aResp->res);
1679 return;
1680 }
1681 // Assume only 1 system D-Bus object
1682 // Throw an error if there is more than 1
1683 if (subtree.size() > 1)
1684 {
1685 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1686 messages::internalError(aResp->res);
1687 return;
1688 }
1689 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1690 {
1691 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1692 messages::internalError(aResp->res);
1693 return;
1694 }
1695
1696 const std::string& path = subtree[0].first;
1697 const std::string& service = subtree[0].second.begin()->first;
1698
1699 if (service.empty())
1700 {
1701 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1702 messages::internalError(aResp->res);
1703 return;
1704 }
1705
1706 crow::connections::systemBus->async_method_call(
1707 [aResp](const boost::system::error_code ec2) {
1708 if (ec2)
1709 {
1710 BMCWEB_LOG_DEBUG
1711 << "D-Bus response error on AssetTag Set " << ec2;
1712 messages::internalError(aResp->res);
1713 return;
1714 }
1715 },
1716 service, path, "org.freedesktop.DBus.Properties", "Set",
1717 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001718 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001719 },
1720 "xyz.openbmc_project.ObjectMapper",
1721 "/xyz/openbmc_project/object_mapper",
1722 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1723 "/xyz/openbmc_project/inventory", int32_t(0),
1724 std::array<const char*, 1>{
1725 "xyz.openbmc_project.Inventory.Item.System"});
1726}
1727
1728/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001729 * @brief Sets automaticRetry (Auto Reboot)
1730 *
1731 * @param[in] aResp Shared pointer for generating response message.
1732 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1733 *
1734 * @return None.
1735 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001736inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001737 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001738{
1739 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1740
1741 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001742 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001743
1744 if (automaticRetryConfig == "Disabled")
1745 {
1746 autoRebootEnabled = false;
1747 }
1748 else if (automaticRetryConfig == "RetryAttempts")
1749 {
1750 autoRebootEnabled = true;
1751 }
1752 else
1753 {
George Liu0fda0f12021-11-16 10:06:17 +08001754 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001755 << automaticRetryConfig;
1756 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1757 "AutomaticRetryConfig");
1758 return;
1759 }
1760
1761 crow::connections::systemBus->async_method_call(
1762 [aResp](const boost::system::error_code ec) {
1763 if (ec)
1764 {
1765 messages::internalError(aResp->res);
1766 return;
1767 }
1768 },
1769 "xyz.openbmc_project.Settings",
1770 "/xyz/openbmc_project/control/host0/auto_reboot",
1771 "org.freedesktop.DBus.Properties", "Set",
1772 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001773 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001774}
1775
1776/**
George Liuc6a620f2020-04-10 17:18:11 +08001777 * @brief Sets power restore policy properties.
1778 *
1779 * @param[in] aResp Shared pointer for generating response message.
1780 * @param[in] policy power restore policy properties from request.
1781 *
1782 * @return None.
1783 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001784inline void
1785 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1786 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001787{
1788 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1789
1790 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001791 {"AlwaysOn",
1792 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1793 {"AlwaysOff",
1794 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1795 {"LastState",
1796 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001797
1798 std::string powerRestorPolicy;
1799
Gunnar Mills4e69c902021-01-05 19:50:11 -06001800 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001801 if (policyMapsIt == policyMaps.end())
1802 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001803 messages::propertyValueNotInList(aResp->res, policy,
1804 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001805 return;
1806 }
1807
1808 powerRestorPolicy = policyMapsIt->second;
1809
1810 crow::connections::systemBus->async_method_call(
1811 [aResp](const boost::system::error_code ec) {
1812 if (ec)
1813 {
1814 messages::internalError(aResp->res);
1815 return;
1816 }
1817 },
1818 "xyz.openbmc_project.Settings",
1819 "/xyz/openbmc_project/control/host0/power_restore_policy",
1820 "org.freedesktop.DBus.Properties", "Set",
1821 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001822 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001823}
1824
AppaRao Pulia6349912019-10-18 17:16:08 +05301825#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1826/**
1827 * @brief Retrieves provisioning status
1828 *
1829 * @param[in] aResp Shared pointer for completing asynchronous calls.
1830 *
1831 * @return None.
1832 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001833inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301834{
1835 BMCWEB_LOG_DEBUG << "Get OEM information.";
1836 crow::connections::systemBus->async_method_call(
1837 [aResp](const boost::system::error_code ec,
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001838 const std::vector<
1839 std::pair<std::string, dbus::utility::DbusVariantType>>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001840 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301841 nlohmann::json& oemPFR =
1842 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001843 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1844 "#OemComputerSystem.OpenBmc";
1845 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1846
AppaRao Pulia6349912019-10-18 17:16:08 +05301847 if (ec)
1848 {
1849 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301850 // not an error, don't have to have the interface
1851 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301852 return;
1853 }
1854
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001855 const bool* provState = nullptr;
1856 const bool* lockState = nullptr;
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001857 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1858 property : propertiesList)
AppaRao Pulia6349912019-10-18 17:16:08 +05301859 {
1860 if (property.first == "UfmProvisioned")
1861 {
1862 provState = std::get_if<bool>(&property.second);
1863 }
1864 else if (property.first == "UfmLocked")
1865 {
1866 lockState = std::get_if<bool>(&property.second);
1867 }
1868 }
1869
1870 if ((provState == nullptr) || (lockState == nullptr))
1871 {
1872 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1873 messages::internalError(aResp->res);
1874 return;
1875 }
1876
AppaRao Pulia6349912019-10-18 17:16:08 +05301877 if (*provState == true)
1878 {
1879 if (*lockState == true)
1880 {
1881 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1882 }
1883 else
1884 {
1885 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1886 }
1887 }
1888 else
1889 {
1890 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1891 }
1892 },
1893 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1894 "org.freedesktop.DBus.Properties", "GetAll",
1895 "xyz.openbmc_project.PFR.Attributes");
1896}
1897#endif
1898
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301899/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001900 * @brief Translate the PowerMode to a response message.
1901 *
1902 * @param[in] aResp Shared pointer for generating response message.
1903 * @param[in] modeValue PowerMode value to be translated
1904 *
1905 * @return None.
1906 */
1907inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1908 const std::string& modeValue)
1909{
1910 std::string modeString;
1911
George Liu0fda0f12021-11-16 10:06:17 +08001912 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001913 {
1914 aResp->res.jsonValue["PowerMode"] = "Static";
1915 }
George Liu0fda0f12021-11-16 10:06:17 +08001916 else if (
1917 modeValue ==
1918 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001919 {
1920 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1921 }
George Liu0fda0f12021-11-16 10:06:17 +08001922 else if (modeValue ==
1923 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001924 {
1925 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1926 }
George Liu0fda0f12021-11-16 10:06:17 +08001927 else if (modeValue ==
1928 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001929 {
1930 aResp->res.jsonValue["PowerMode"] = "OEM";
1931 }
1932 else
1933 {
1934 // Any other values would be invalid
1935 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1936 messages::internalError(aResp->res);
1937 }
1938}
1939
1940/**
1941 * @brief Retrieves system power mode
1942 *
1943 * @param[in] aResp Shared pointer for generating response message.
1944 *
1945 * @return None.
1946 */
1947inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1948{
1949 BMCWEB_LOG_DEBUG << "Get power mode.";
1950
1951 // Get Power Mode object path:
1952 crow::connections::systemBus->async_method_call(
1953 [aResp](
1954 const boost::system::error_code ec,
1955 const std::vector<std::pair<
1956 std::string,
1957 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1958 subtree) {
1959 if (ec)
1960 {
1961 BMCWEB_LOG_DEBUG
1962 << "DBUS response error on Power.Mode GetSubTree " << ec;
1963 // This is an optional D-Bus object so just return if
1964 // error occurs
1965 return;
1966 }
1967 if (subtree.empty())
1968 {
1969 // As noted above, this is an optional interface so just return
1970 // if there is no instance found
1971 return;
1972 }
1973 if (subtree.size() > 1)
1974 {
1975 // More then one PowerMode object is not supported and is an
1976 // error
1977 BMCWEB_LOG_DEBUG
1978 << "Found more than 1 system D-Bus Power.Mode objects: "
1979 << subtree.size();
1980 messages::internalError(aResp->res);
1981 return;
1982 }
1983 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1984 {
1985 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1986 messages::internalError(aResp->res);
1987 return;
1988 }
1989 const std::string& path = subtree[0].first;
1990 const std::string& service = subtree[0].second.begin()->first;
1991 if (service.empty())
1992 {
1993 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1994 messages::internalError(aResp->res);
1995 return;
1996 }
1997 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001998 sdbusplus::asio::getProperty<std::string>(
1999 *crow::connections::systemBus, service, path,
2000 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05002001 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002002 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002003 if (ec)
2004 {
2005 BMCWEB_LOG_DEBUG
2006 << "DBUS response error on PowerMode Get: " << ec;
2007 messages::internalError(aResp->res);
2008 return;
2009 }
2010
Chris Cain3a2d04242021-05-28 16:57:10 -05002011 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2012 {"Static", "MaximumPerformance", "PowerSaving"};
2013
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002014 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2015 translatePowerMode(aResp, pmode);
2016 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002017 },
2018 "xyz.openbmc_project.ObjectMapper",
2019 "/xyz/openbmc_project/object_mapper",
2020 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2021 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2022}
2023
2024/**
2025 * @brief Validate the specified mode is valid and return the PowerMode
2026 * name associated with that string
2027 *
2028 * @param[in] aResp Shared pointer for generating response message.
2029 * @param[in] modeString String representing the desired PowerMode
2030 *
2031 * @return PowerMode value or empty string if mode is not valid
2032 */
2033inline std::string
2034 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2035 const std::string& modeString)
2036{
2037 std::string mode;
2038
2039 if (modeString == "Static")
2040 {
2041 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2042 }
2043 else if (modeString == "MaximumPerformance")
2044 {
George Liu0fda0f12021-11-16 10:06:17 +08002045 mode =
2046 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002047 }
2048 else if (modeString == "PowerSaving")
2049 {
2050 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2051 }
2052 else
2053 {
2054 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2055 }
2056 return mode;
2057}
2058
2059/**
2060 * @brief Sets system power mode.
2061 *
2062 * @param[in] aResp Shared pointer for generating response message.
2063 * @param[in] pmode System power mode from request.
2064 *
2065 * @return None.
2066 */
2067inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2068 const std::string& pmode)
2069{
2070 BMCWEB_LOG_DEBUG << "Set power mode.";
2071
2072 std::string powerMode = validatePowerMode(aResp, pmode);
2073 if (powerMode.empty())
2074 {
2075 return;
2076 }
2077
2078 // Get Power Mode object path:
2079 crow::connections::systemBus->async_method_call(
2080 [aResp, powerMode](
2081 const boost::system::error_code ec,
2082 const std::vector<std::pair<
2083 std::string,
2084 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2085 subtree) {
2086 if (ec)
2087 {
2088 BMCWEB_LOG_DEBUG
2089 << "DBUS response error on Power.Mode GetSubTree " << ec;
2090 // This is an optional D-Bus object, but user attempted to patch
2091 messages::internalError(aResp->res);
2092 return;
2093 }
2094 if (subtree.empty())
2095 {
2096 // This is an optional D-Bus object, but user attempted to patch
2097 messages::resourceNotFound(aResp->res, "ComputerSystem",
2098 "PowerMode");
2099 return;
2100 }
2101 if (subtree.size() > 1)
2102 {
2103 // More then one PowerMode object is not supported and is an
2104 // error
2105 BMCWEB_LOG_DEBUG
2106 << "Found more than 1 system D-Bus Power.Mode objects: "
2107 << subtree.size();
2108 messages::internalError(aResp->res);
2109 return;
2110 }
2111 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2112 {
2113 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2114 messages::internalError(aResp->res);
2115 return;
2116 }
2117 const std::string& path = subtree[0].first;
2118 const std::string& service = subtree[0].second.begin()->first;
2119 if (service.empty())
2120 {
2121 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2122 messages::internalError(aResp->res);
2123 return;
2124 }
2125
2126 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2127 << path;
2128
2129 // Set the Power Mode property
2130 crow::connections::systemBus->async_method_call(
2131 [aResp](const boost::system::error_code ec) {
2132 if (ec)
2133 {
2134 messages::internalError(aResp->res);
2135 return;
2136 }
2137 },
2138 service, path, "org.freedesktop.DBus.Properties", "Set",
2139 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002140 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002141 },
2142 "xyz.openbmc_project.ObjectMapper",
2143 "/xyz/openbmc_project/object_mapper",
2144 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2145 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2146}
2147
2148/**
Yong Li51709ff2019-09-30 14:13:04 +08002149 * @brief Translates watchdog timeout action DBUS property value to redfish.
2150 *
2151 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2152 *
2153 * @return Returns as a string, the timeout action in Redfish terms. If
2154 * translation cannot be done, returns an empty string.
2155 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002156inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002157{
2158 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2159 {
2160 return "None";
2161 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002162 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002163 {
2164 return "ResetSystem";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002167 {
2168 return "PowerDown";
2169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002170 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002171 {
2172 return "PowerCycle";
2173 }
2174
2175 return "";
2176}
2177
2178/**
Yong Lic45f0082019-10-10 14:19:01 +08002179 *@brief Translates timeout action from Redfish to DBUS property value.
2180 *
2181 *@param[in] rfAction The timeout action in Redfish.
2182 *
2183 *@return Returns as a string, the time_out action as expected by DBUS.
2184 *If translation cannot be done, returns an empty string.
2185 */
2186
Ed Tanous23a21a12020-07-25 04:45:05 +00002187inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002188{
2189 if (rfAction == "None")
2190 {
2191 return "xyz.openbmc_project.State.Watchdog.Action.None";
2192 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002193 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002194 {
2195 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2196 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002197 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002198 {
2199 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2200 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002201 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002202 {
2203 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2204 }
2205
2206 return "";
2207}
2208
2209/**
Yong Li51709ff2019-09-30 14:13:04 +08002210 * @brief Retrieves host watchdog timer properties over DBUS
2211 *
2212 * @param[in] aResp Shared pointer for completing asynchronous calls.
2213 *
2214 * @return None.
2215 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002216inline void
2217 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002218{
2219 BMCWEB_LOG_DEBUG << "Get host watchodg";
2220 crow::connections::systemBus->async_method_call(
2221 [aResp](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002222 const PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002223 if (ec)
2224 {
2225 // watchdog service is stopped
2226 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2227 return;
2228 }
2229
2230 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2231
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002232 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002233 aResp->res.jsonValue["HostWatchdogTimer"];
2234
2235 // watchdog service is running/enabled
2236 hostWatchdogTimer["Status"]["State"] = "Enabled";
2237
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002238 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002239 {
2240 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2241 if (property.first == "Enabled")
2242 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002243 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002244
Ed Tanouse662eae2022-01-25 10:39:19 -08002245 if (state == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002246 {
2247 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002248 return;
Yong Li51709ff2019-09-30 14:13:04 +08002249 }
2250
2251 hostWatchdogTimer["FunctionEnabled"] = *state;
2252 }
2253 else if (property.first == "ExpireAction")
2254 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002255 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002256 std::get_if<std::string>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002257 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002258 {
2259 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002260 return;
Yong Li51709ff2019-09-30 14:13:04 +08002261 }
2262
2263 std::string action = dbusToRfWatchdogAction(*s);
2264 if (action.empty())
2265 {
2266 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002267 return;
Yong Li51709ff2019-09-30 14:13:04 +08002268 }
2269 hostWatchdogTimer["TimeoutAction"] = action;
2270 }
2271 }
2272 },
2273 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2274 "org.freedesktop.DBus.Properties", "GetAll",
2275 "xyz.openbmc_project.State.Watchdog");
2276}
2277
2278/**
Yong Lic45f0082019-10-10 14:19:01 +08002279 * @brief Sets Host WatchDog Timer properties.
2280 *
2281 * @param[in] aResp Shared pointer for generating response message.
2282 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2283 * RF request.
2284 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2285 *
2286 * @return None.
2287 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002288inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002289 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002290 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002291{
2292 BMCWEB_LOG_DEBUG << "Set host watchdog";
2293
2294 if (wdtTimeOutAction)
2295 {
2296 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2297 // check if TimeOut Action is Valid
2298 if (wdtTimeOutActStr.empty())
2299 {
2300 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2301 << *wdtTimeOutAction;
2302 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2303 "TimeoutAction");
2304 return;
2305 }
2306
2307 crow::connections::systemBus->async_method_call(
2308 [aResp](const boost::system::error_code ec) {
2309 if (ec)
2310 {
2311 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2312 messages::internalError(aResp->res);
2313 return;
2314 }
2315 },
2316 "xyz.openbmc_project.Watchdog",
2317 "/xyz/openbmc_project/watchdog/host0",
2318 "org.freedesktop.DBus.Properties", "Set",
2319 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002320 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002321 }
2322
2323 if (wdtEnable)
2324 {
2325 crow::connections::systemBus->async_method_call(
2326 [aResp](const boost::system::error_code ec) {
2327 if (ec)
2328 {
2329 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2330 messages::internalError(aResp->res);
2331 return;
2332 }
2333 },
2334 "xyz.openbmc_project.Watchdog",
2335 "/xyz/openbmc_project/watchdog/host0",
2336 "org.freedesktop.DBus.Properties", "Set",
2337 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002338 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002339 }
2340}
2341
Chris Cain37bbf982021-09-20 10:53:09 -05002342using ipsPropertiesType =
2343 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2344/**
2345 * @brief Parse the Idle Power Saver properties into json
2346 *
2347 * @param[in] aResp Shared pointer for completing asynchronous calls.
2348 * @param[in] properties IPS property data from DBus.
2349 *
2350 * @return true if successful
2351 */
Ed Tanousf6674222021-11-13 09:41:41 -08002352inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2353 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002354{
2355 for (const auto& property : properties)
2356 {
2357 if (property.first == "Enabled")
2358 {
2359 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002360 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002361 {
2362 return false;
2363 }
2364 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2365 }
2366 else if (property.first == "EnterUtilizationPercent")
2367 {
2368 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002369 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002370 {
2371 return false;
2372 }
2373 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2374 }
2375 else if (property.first == "EnterDwellTime")
2376 {
2377 // Convert Dbus time from milliseconds to seconds
2378 const uint64_t* timeMilliseconds =
2379 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002380 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002381 {
2382 return false;
2383 }
2384 const std::chrono::duration<uint64_t, std::milli> ms(
2385 *timeMilliseconds);
2386 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2387 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2388 .count();
2389 }
2390 else if (property.first == "ExitUtilizationPercent")
2391 {
2392 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002393 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002394 {
2395 return false;
2396 }
2397 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2398 }
2399 else if (property.first == "ExitDwellTime")
2400 {
2401 // Convert Dbus time from milliseconds to seconds
2402 const uint64_t* timeMilliseconds =
2403 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002404 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002405 {
2406 return false;
2407 }
2408 const std::chrono::duration<uint64_t, std::milli> ms(
2409 *timeMilliseconds);
2410 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2411 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2412 .count();
2413 }
2414 else
2415 {
2416 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2417 << property.first;
2418 }
2419 }
2420
2421 return true;
2422}
2423
2424/**
2425 * @brief Retrieves host watchdog timer properties over DBUS
2426 *
2427 * @param[in] aResp Shared pointer for completing asynchronous calls.
2428 *
2429 * @return None.
2430 */
2431inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2432{
2433 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2434
2435 // Get IdlePowerSaver object path:
2436 crow::connections::systemBus->async_method_call(
2437 [aResp](
2438 const boost::system::error_code ec,
2439 const std::vector<std::pair<
2440 std::string,
2441 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2442 subtree) {
2443 if (ec)
2444 {
2445 BMCWEB_LOG_DEBUG
2446 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2447 << ec;
2448 messages::internalError(aResp->res);
2449 return;
2450 }
2451 if (subtree.empty())
2452 {
2453 // This is an optional interface so just return
2454 // if there is no instance found
2455 BMCWEB_LOG_DEBUG << "No instances found";
2456 return;
2457 }
2458 if (subtree.size() > 1)
2459 {
2460 // More then one PowerIdlePowerSaver object is not supported and
2461 // is an error
2462 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2463 "Power.IdlePowerSaver objects: "
2464 << subtree.size();
2465 messages::internalError(aResp->res);
2466 return;
2467 }
2468 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2469 {
2470 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2471 messages::internalError(aResp->res);
2472 return;
2473 }
2474 const std::string& path = subtree[0].first;
2475 const std::string& service = subtree[0].second.begin()->first;
2476 if (service.empty())
2477 {
2478 BMCWEB_LOG_DEBUG
2479 << "Power.IdlePowerSaver service mapper error!";
2480 messages::internalError(aResp->res);
2481 return;
2482 }
2483
2484 // Valid IdlePowerSaver object found, now read the current values
2485 crow::connections::systemBus->async_method_call(
2486 [aResp](const boost::system::error_code ec,
2487 ipsPropertiesType& properties) {
2488 if (ec)
2489 {
2490 BMCWEB_LOG_ERROR
2491 << "DBUS response error on IdlePowerSaver GetAll: "
2492 << ec;
2493 messages::internalError(aResp->res);
2494 return;
2495 }
2496
Ed Tanouse05aec52022-01-25 10:28:56 -08002497 if (!parseIpsProperties(aResp, properties))
Chris Cain37bbf982021-09-20 10:53:09 -05002498 {
2499 messages::internalError(aResp->res);
2500 return;
2501 }
2502 },
2503 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2504 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2505 },
2506 "xyz.openbmc_project.ObjectMapper",
2507 "/xyz/openbmc_project/object_mapper",
2508 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2509 std::array<const char*, 1>{
2510 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2511
2512 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2513}
2514
2515/**
2516 * @brief Sets Idle Power Saver properties.
2517 *
2518 * @param[in] aResp Shared pointer for generating response message.
2519 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2520 * RF request.
2521 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2522 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2523 * before entering idle state.
2524 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2525 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2526 * before exiting idle state
2527 *
2528 * @return None.
2529 */
2530inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2531 const std::optional<bool> ipsEnable,
2532 const std::optional<uint8_t> ipsEnterUtil,
2533 const std::optional<uint64_t> ipsEnterTime,
2534 const std::optional<uint8_t> ipsExitUtil,
2535 const std::optional<uint64_t> ipsExitTime)
2536{
2537 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2538
2539 // Get IdlePowerSaver object path:
2540 crow::connections::systemBus->async_method_call(
2541 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2542 ipsExitTime](
2543 const boost::system::error_code ec,
2544 const std::vector<std::pair<
2545 std::string,
2546 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2547 subtree) {
2548 if (ec)
2549 {
2550 BMCWEB_LOG_DEBUG
2551 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2552 << ec;
2553 messages::internalError(aResp->res);
2554 return;
2555 }
2556 if (subtree.empty())
2557 {
2558 // This is an optional D-Bus object, but user attempted to patch
2559 messages::resourceNotFound(aResp->res, "ComputerSystem",
2560 "IdlePowerSaver");
2561 return;
2562 }
2563 if (subtree.size() > 1)
2564 {
2565 // More then one PowerIdlePowerSaver object is not supported and
2566 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002567 BMCWEB_LOG_DEBUG
2568 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2569 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002570 messages::internalError(aResp->res);
2571 return;
2572 }
2573 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2574 {
2575 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2576 messages::internalError(aResp->res);
2577 return;
2578 }
2579 const std::string& path = subtree[0].first;
2580 const std::string& service = subtree[0].second.begin()->first;
2581 if (service.empty())
2582 {
2583 BMCWEB_LOG_DEBUG
2584 << "Power.IdlePowerSaver service mapper error!";
2585 messages::internalError(aResp->res);
2586 return;
2587 }
2588
2589 // Valid Power IdlePowerSaver object found, now set any values that
2590 // need to be updated
2591
2592 if (ipsEnable)
2593 {
2594 crow::connections::systemBus->async_method_call(
2595 [aResp](const boost::system::error_code ec) {
2596 if (ec)
2597 {
2598 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2599 messages::internalError(aResp->res);
2600 return;
2601 }
2602 },
2603 service, path, "org.freedesktop.DBus.Properties", "Set",
2604 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002605 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002606 }
2607 if (ipsEnterUtil)
2608 {
2609 crow::connections::systemBus->async_method_call(
2610 [aResp](const boost::system::error_code ec) {
2611 if (ec)
2612 {
2613 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2614 messages::internalError(aResp->res);
2615 return;
2616 }
2617 },
2618 service, path, "org.freedesktop.DBus.Properties", "Set",
2619 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2620 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002621 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002622 }
2623 if (ipsEnterTime)
2624 {
2625 // Convert from seconds into milliseconds for DBus
2626 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2627 crow::connections::systemBus->async_method_call(
2628 [aResp](const boost::system::error_code ec) {
2629 if (ec)
2630 {
2631 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2632 messages::internalError(aResp->res);
2633 return;
2634 }
2635 },
2636 service, path, "org.freedesktop.DBus.Properties", "Set",
2637 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002638 "EnterDwellTime",
2639 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002640 }
2641 if (ipsExitUtil)
2642 {
2643 crow::connections::systemBus->async_method_call(
2644 [aResp](const boost::system::error_code ec) {
2645 if (ec)
2646 {
2647 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2648 messages::internalError(aResp->res);
2649 return;
2650 }
2651 },
2652 service, path, "org.freedesktop.DBus.Properties", "Set",
2653 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2654 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002655 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002656 }
2657 if (ipsExitTime)
2658 {
2659 // Convert from seconds into milliseconds for DBus
2660 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2661 crow::connections::systemBus->async_method_call(
2662 [aResp](const boost::system::error_code ec) {
2663 if (ec)
2664 {
2665 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2666 messages::internalError(aResp->res);
2667 return;
2668 }
2669 },
2670 service, path, "org.freedesktop.DBus.Properties", "Set",
2671 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002672 "ExitDwellTime",
2673 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002674 }
2675 },
2676 "xyz.openbmc_project.ObjectMapper",
2677 "/xyz/openbmc_project/object_mapper",
2678 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2679 std::array<const char*, 1>{
2680 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2681
2682 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2683}
2684
Yong Lic45f0082019-10-10 14:19:01 +08002685/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002686 * SystemsCollection derived class for delivering ComputerSystems Collection
2687 * Schema
2688 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002689inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002690{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002691 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002692 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002693 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002694 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002695 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2696 asyncResp->res.jsonValue["@odata.type"] =
2697 "#ComputerSystemCollection.ComputerSystemCollection";
2698 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2699 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002700
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002701 sdbusplus::asio::getProperty<std::string>(
2702 *crow::connections::systemBus,
2703 "xyz.openbmc_project.Settings",
2704 "/xyz/openbmc_project/network/hypervisor",
2705 "xyz.openbmc_project.Network.SystemConfiguration",
2706 "HostName",
2707 [asyncResp](const boost::system::error_code ec,
2708 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002709 nlohmann::json& ifaceArray =
2710 asyncResp->res.jsonValue["Members"];
2711 ifaceArray = nlohmann::json::array();
2712 auto& count =
2713 asyncResp->res.jsonValue["Members@odata.count"];
2714 ifaceArray.push_back(
2715 {{"@odata.id", "/redfish/v1/Systems/system"}});
2716 count = ifaceArray.size();
2717 if (!ec)
2718 {
2719 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2720 ifaceArray.push_back(
2721 {{"@odata.id",
2722 "/redfish/v1/Systems/hypervisor"}});
2723 count = ifaceArray.size();
2724 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002725 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002726 });
2727}
Sunitha Harish462023a2020-02-19 08:34:59 -06002728
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002729/**
2730 * Function transceives data with dbus directly.
2731 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002732inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002733{
2734 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2735 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2736 constexpr char const* interfaceName =
2737 "xyz.openbmc_project.Control.Host.NMI";
2738 constexpr char const* method = "NMI";
2739
2740 crow::connections::systemBus->async_method_call(
2741 [asyncResp](const boost::system::error_code ec) {
2742 if (ec)
2743 {
2744 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2745 messages::internalError(asyncResp->res);
2746 return;
2747 }
2748 messages::success(asyncResp->res);
2749 },
2750 serviceName, objectPath, interfaceName, method);
2751}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002752
2753/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002754 * SystemActionsReset class supports handle POST method for Reset action.
2755 * The class retrieves and sends data directly to D-Bus.
2756 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002757inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002758{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002759 /**
2760 * Function handles POST method request.
2761 * Analyzes POST body message before sends Reset request data to D-Bus.
2762 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002763 BMCWEB_ROUTE(app,
2764 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002765 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002766 .methods(
2767 boost::beast::http::verb::
2768 post)([](const crow::Request& req,
2769 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2770 std::string resetType;
Willy Tu15ed6782021-12-14 11:03:16 -08002771 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2772 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002773 {
2774 return;
2775 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002776
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002777 // Get the command and host vs. chassis
2778 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002779 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002780 if ((resetType == "On") || (resetType == "ForceOn"))
2781 {
2782 command = "xyz.openbmc_project.State.Host.Transition.On";
2783 hostCommand = true;
2784 }
2785 else if (resetType == "ForceOff")
2786 {
2787 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2788 hostCommand = false;
2789 }
2790 else if (resetType == "ForceRestart")
2791 {
2792 command =
2793 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2794 hostCommand = true;
2795 }
2796 else if (resetType == "GracefulShutdown")
2797 {
2798 command = "xyz.openbmc_project.State.Host.Transition.Off";
2799 hostCommand = true;
2800 }
2801 else if (resetType == "GracefulRestart")
2802 {
George Liu0fda0f12021-11-16 10:06:17 +08002803 command =
2804 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002805 hostCommand = true;
2806 }
2807 else if (resetType == "PowerCycle")
2808 {
2809 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2810 hostCommand = true;
2811 }
2812 else if (resetType == "Nmi")
2813 {
2814 doNMI(asyncResp);
2815 return;
2816 }
2817 else
2818 {
2819 messages::actionParameterUnknown(asyncResp->res, "Reset",
2820 resetType);
2821 return;
2822 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002823
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002824 if (hostCommand)
2825 {
2826 crow::connections::systemBus->async_method_call(
2827 [asyncResp, resetType](const boost::system::error_code ec) {
2828 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002829 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002830 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2831 if (ec.value() ==
2832 boost::asio::error::invalid_argument)
2833 {
2834 messages::actionParameterNotSupported(
2835 asyncResp->res, resetType, "Reset");
2836 }
2837 else
2838 {
2839 messages::internalError(asyncResp->res);
2840 }
2841 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002842 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843 messages::success(asyncResp->res);
2844 },
2845 "xyz.openbmc_project.State.Host",
2846 "/xyz/openbmc_project/state/host0",
2847 "org.freedesktop.DBus.Properties", "Set",
2848 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002849 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002850 }
2851 else
2852 {
2853 crow::connections::systemBus->async_method_call(
2854 [asyncResp, resetType](const boost::system::error_code ec) {
2855 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002856 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002857 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2858 if (ec.value() ==
2859 boost::asio::error::invalid_argument)
2860 {
2861 messages::actionParameterNotSupported(
2862 asyncResp->res, resetType, "Reset");
2863 }
2864 else
2865 {
2866 messages::internalError(asyncResp->res);
2867 }
2868 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002869 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002870 messages::success(asyncResp->res);
2871 },
2872 "xyz.openbmc_project.State.Chassis",
2873 "/xyz/openbmc_project/state/chassis0",
2874 "org.freedesktop.DBus.Properties", "Set",
2875 "xyz.openbmc_project.State.Chassis",
2876 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002877 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002878 }
2879 });
2880}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002881
2882/**
Ed Tanous66173382018-08-15 18:20:59 -07002883 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002884 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002885inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002886{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002887
Ed Tanous1abe55e2018-09-05 08:30:59 -07002888 /**
2889 * Functions triggers appropriate requests on DBus
2890 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002891 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002892 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002893 .methods(
2894 boost::beast::http::verb::
2895 get)([](const crow::Request&,
2896 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2897 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002898 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002899 asyncResp->res.jsonValue["Name"] = "system";
2900 asyncResp->res.jsonValue["Id"] = "system";
2901 asyncResp->res.jsonValue["SystemType"] = "Physical";
2902 asyncResp->res.jsonValue["Description"] = "Computer System";
2903 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2904 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2905 "Disabled";
2906 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2907 uint64_t(0);
2908 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2909 "Disabled";
2910 asyncResp->res.jsonValue["@odata.id"] =
2911 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002912
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002913 asyncResp->res.jsonValue["Processors"] = {
2914 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2915 asyncResp->res.jsonValue["Memory"] = {
2916 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2917 asyncResp->res.jsonValue["Storage"] = {
2918 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002919
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002920 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2921 {"target",
2922 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2923 {"@Redfish.ActionInfo",
2924 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002925
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002926 asyncResp->res.jsonValue["LogServices"] = {
2927 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002928
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002929 asyncResp->res.jsonValue["Bios"] = {
2930 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002931
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002932 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2933 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002934
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002935 asyncResp->res.jsonValue["Status"] = {
2936 {"Health", "OK"},
2937 {"State", "Enabled"},
2938 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002939
2940 // Fill in SerialConsole info
2941 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2942 15;
2943 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2944 {"ServiceEnabled", true},
2945 };
2946 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2947 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2948 {"ServiceEnabled", true},
2949 {"Port", 2200},
2950 // https://github.com/openbmc/docs/blob/master/console.md
2951 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2952 };
2953
2954#ifdef BMCWEB_ENABLE_KVM
2955 // Fill in GraphicalConsole info
2956 asyncResp->res.jsonValue["GraphicalConsole"] = {
2957 {"ServiceEnabled", true},
2958 {"MaxConcurrentSessions", 4},
2959 {"ConnectTypesSupported", {"KVMIP"}},
2960 };
2961#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002962 constexpr const std::array<const char*, 4> inventoryForSystems = {
2963 "xyz.openbmc_project.Inventory.Item.Dimm",
2964 "xyz.openbmc_project.Inventory.Item.Cpu",
2965 "xyz.openbmc_project.Inventory.Item.Drive",
2966 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002967
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002968 auto health = std::make_shared<HealthPopulate>(asyncResp);
2969 crow::connections::systemBus->async_method_call(
2970 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002971 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002972 if (ec)
2973 {
2974 // no inventory
2975 return;
2976 }
2977
Ed Tanous914e2d52022-01-07 11:38:34 -08002978 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002979 },
2980 "xyz.openbmc_project.ObjectMapper",
2981 "/xyz/openbmc_project/object_mapper",
2982 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2983 int32_t(0), inventoryForSystems);
2984
2985 health->populate();
2986
2987 getMainChassisId(
2988 asyncResp, [](const std::string& chassisId,
2989 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2990 aRsp->res.jsonValue["Links"]["Chassis"] = {
2991 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2992 });
2993
2994 getLocationIndicatorActive(asyncResp);
2995 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2996 getIndicatorLedState(asyncResp);
2997 getComputerSystem(asyncResp, health);
2998 getHostState(asyncResp);
2999 getBootProperties(asyncResp);
3000 getBootProgress(asyncResp);
3001 getPCIeDeviceList(asyncResp, "PCIeDevices");
3002 getHostWatchdogTimer(asyncResp);
3003 getPowerRestorePolicy(asyncResp);
3004 getAutomaticRetry(asyncResp);
3005 getLastResetTime(asyncResp);
3006#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
3007 getProvisioningStatus(asyncResp);
3008#endif
Ali Ahmed19817712021-06-29 17:01:52 -05003009 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05003010 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003011 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003012 });
3013 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003014 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003015 .methods(boost::beast::http::verb::patch)(
3016 [](const crow::Request& req,
3017 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3018 std::optional<bool> locationIndicatorActive;
3019 std::optional<std::string> indicatorLed;
3020 std::optional<nlohmann::json> bootProps;
3021 std::optional<nlohmann::json> wdtTimerProps;
3022 std::optional<std::string> assetTag;
3023 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003024 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003025 std::optional<nlohmann::json> ipsProps;
Willy Tu15ed6782021-12-14 11:03:16 -08003026 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003027 req, asyncResp->res, "IndicatorLED", indicatorLed,
3028 "LocationIndicatorActive", locationIndicatorActive,
3029 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3030 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003031 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3032 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003033 {
James Feistb49ac872019-05-21 15:12:01 -07003034 return;
3035 }
3036
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003037 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003038
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039 if (assetTag)
3040 {
3041 setAssetTag(asyncResp, *assetTag);
3042 }
James Feistb49ac872019-05-21 15:12:01 -07003043
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003044 if (wdtTimerProps)
3045 {
3046 std::optional<bool> wdtEnable;
3047 std::optional<std::string> wdtTimeOutAction;
3048
3049 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3050 "FunctionEnabled", wdtEnable,
3051 "TimeoutAction", wdtTimeOutAction))
3052 {
3053 return;
3054 }
3055 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3056 }
3057
3058 if (bootProps)
3059 {
3060 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003061 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003062 std::optional<std::string> bootEnable;
3063 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003064 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003065
3066 if (!json_util::readJson(
3067 *bootProps, asyncResp->res,
3068 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003069 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003070 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003071 "AutomaticRetryConfig", automaticRetryConfig,
3072 "TrustedModuleRequiredToBoot",
3073 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003074 {
3075 return;
3076 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003077
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003078 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003079 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003080 setBootProperties(asyncResp, bootSource, bootType,
3081 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003082 }
3083 if (automaticRetryConfig)
3084 {
3085 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3086 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003087
3088 if (trustedModuleRequiredToBoot)
3089 {
3090 setTrustedModuleRequiredToBoot(
3091 asyncResp, *trustedModuleRequiredToBoot);
3092 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003093 }
3094
3095 if (locationIndicatorActive)
3096 {
3097 setLocationIndicatorActive(asyncResp,
3098 *locationIndicatorActive);
3099 }
3100
3101 // TODO (Gunnar): Remove IndicatorLED after enough time has
3102 // passed
3103 if (indicatorLed)
3104 {
3105 setIndicatorLedState(asyncResp, *indicatorLed);
3106 asyncResp->res.addHeader(
3107 boost::beast::http::field::warning,
3108 "299 - \"IndicatorLED is deprecated. Use "
3109 "LocationIndicatorActive instead.\"");
3110 }
3111
3112 if (powerRestorePolicy)
3113 {
3114 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3115 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003116
3117 if (powerMode)
3118 {
3119 setPowerMode(asyncResp, *powerMode);
3120 }
Chris Cain37bbf982021-09-20 10:53:09 -05003121
3122 if (ipsProps)
3123 {
3124 std::optional<bool> ipsEnable;
3125 std::optional<uint8_t> ipsEnterUtil;
3126 std::optional<uint64_t> ipsEnterTime;
3127 std::optional<uint8_t> ipsExitUtil;
3128 std::optional<uint64_t> ipsExitTime;
3129
3130 if (!json_util::readJson(
3131 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3132 "EnterUtilizationPercent", ipsEnterUtil,
3133 "EnterDwellTimeSeconds", ipsEnterTime,
3134 "ExitUtilizationPercent", ipsExitUtil,
3135 "ExitDwellTimeSeconds", ipsExitTime))
3136 {
3137 return;
3138 }
3139 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3140 ipsEnterTime, ipsExitUtil, ipsExitTime);
3141 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003142 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003143}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303144
3145/**
3146 * SystemResetActionInfo derived class for delivering Computer Systems
3147 * ResetType AllowableValues using ResetInfo schema.
3148 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003149inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303150{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303151
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303152 /**
3153 * Functions triggers appropriate requests on DBus
3154 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003155 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003156 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003157 .methods(boost::beast::http::verb::get)(
3158 [](const crow::Request&,
3159 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3160 asyncResp->res.jsonValue = {
3161 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3162 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3163 {"Name", "Reset Action Info"},
3164 {"Id", "ResetActionInfo"},
3165 {"Parameters",
3166 {{{"Name", "ResetType"},
3167 {"Required", true},
3168 {"DataType", "String"},
3169 {"AllowableValues",
3170 {"On", "ForceOff", "ForceOn", "ForceRestart",
3171 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3172 "Nmi"}}}}}};
3173 });
3174}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003175} // namespace redfish