blob: 604f5510744f88f4942e05c85b5da3158b9cd848 [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 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070058 if (isDimmFunctional == true)
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
Jonathan Doman1e1e5982021-06-11 09:36:17 -070080 if (isCpuPresent == true)
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"];
84 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 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700117 if (isCpuFunctional == true)
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
179 if (!coreCountVal)
180 {
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 {
557 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700558 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700559 return;
560 }
Ed Tanous66173382018-08-15 18:20:59 -0700561
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700562 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
563 // Verify Host State
564 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700565 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700566 aResp->res.jsonValue["PowerState"] = "On";
567 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700568 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700569 else if (hostState ==
570 "xyz.openbmc_project.State.Host.HostState.Quiesced")
571 {
572 aResp->res.jsonValue["PowerState"] = "On";
573 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
574 }
575 else if (hostState ==
576 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
577 {
578 aResp->res.jsonValue["PowerState"] = "On";
579 aResp->res.jsonValue["Status"]["State"] = "InTest";
580 }
581 else if (
582 hostState ==
583 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
584 {
585 aResp->res.jsonValue["PowerState"] = "PoweringOn";
586 aResp->res.jsonValue["Status"]["State"] = "Starting";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOff";
593 aResp->res.jsonValue["Status"]["State"] = "Disabled";
594 }
595 else
596 {
597 aResp->res.jsonValue["PowerState"] = "Off";
598 aResp->res.jsonValue["Status"]["State"] = "Disabled";
599 }
600 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700601}
602
603/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500604 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530605 *
606 * @param[in] dbusSource The boot source in DBUS speak.
607 *
608 * @return Returns as a string, the boot source in Redfish terms. If translation
609 * cannot be done, returns an empty string.
610 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000611inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530612{
613 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
614 {
615 return "None";
616 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700617 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530618 {
619 return "Hdd";
620 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700621 if (dbusSource ==
622 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530623 {
624 return "Cd";
625 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700626 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530627 {
628 return "Pxe";
629 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700630 if (dbusSource ==
631 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700632 {
633 return "Usb";
634 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700635 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530636}
637
638/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300639 * @brief Translates boot type DBUS property value to redfish.
640 *
641 * @param[in] dbusType The boot type in DBUS speak.
642 *
643 * @return Returns as a string, the boot type in Redfish terms. If translation
644 * cannot be done, returns an empty string.
645 */
646inline std::string dbusToRfBootType(const std::string& dbusType)
647{
648 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
649 {
650 return "Legacy";
651 }
652 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
653 {
654 return "UEFI";
655 }
656 return "";
657}
658
659/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500660 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661 *
662 * @param[in] dbusMode The boot mode in DBUS speak.
663 *
664 * @return Returns as a string, the boot mode in Redfish terms. If translation
665 * cannot be done, returns an empty string.
666 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000667inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668{
669 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
670 {
671 return "None";
672 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700673 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674 {
675 return "Diags";
676 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700677 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530678 {
679 return "BiosSetup";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530682}
683
684/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600685 * @brief Translates boot progress DBUS property value to redfish.
686 *
687 * @param[in] dbusBootProgress The boot progress in DBUS speak.
688 *
689 * @return Returns as a string, the boot progress in Redfish terms. If
690 * translation cannot be done, returns "None".
691 */
692inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
693{
694 // Now convert the D-Bus BootProgress to the appropriate Redfish
695 // enum
696 std::string rfBpLastState = "None";
697 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
698 "ProgressStages.Unspecified")
699 {
700 rfBpLastState = "None";
701 }
702 else if (dbusBootProgress ==
703 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
704 "PrimaryProcInit")
705 {
706 rfBpLastState = "PrimaryProcessorInitializationStarted";
707 }
708 else if (dbusBootProgress ==
709 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
710 "BusInit")
711 {
712 rfBpLastState = "BusInitializationStarted";
713 }
714 else if (dbusBootProgress ==
715 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
716 "MemoryInit")
717 {
718 rfBpLastState = "MemoryInitializationStarted";
719 }
720 else if (dbusBootProgress ==
721 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
722 "SecondaryProcInit")
723 {
724 rfBpLastState = "SecondaryProcessorInitializationStarted";
725 }
726 else if (dbusBootProgress ==
727 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
728 "PCIInit")
729 {
730 rfBpLastState = "PCIResourceConfigStarted";
731 }
732 else if (dbusBootProgress ==
733 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
734 "SystemSetup")
735 {
736 rfBpLastState = "SetupEntered";
737 }
738 else if (dbusBootProgress ==
739 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
740 "SystemInitComplete")
741 {
742 rfBpLastState = "SystemHardwareInitializationComplete";
743 }
744 else if (dbusBootProgress ==
745 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
746 "OSStart")
747 {
748 rfBpLastState = "OSBootStarted";
749 }
750 else if (dbusBootProgress ==
751 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
752 "OSRunning")
753 {
754 rfBpLastState = "OSRunning";
755 }
756 else
757 {
758 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
759 << dbusBootProgress;
760 // Just return the default
761 }
762 return rfBpLastState;
763}
764
765/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500766 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530767 *
768 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700769 * @param[out] bootSource The DBus source
770 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530771 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700772 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800774inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500775 const std::string& rfSource,
776 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300778 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
779 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 if (rfSource == "None")
782 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700785 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530786 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
788 }
789 else if (rfSource == "Hdd")
790 {
791 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
792 }
793 else if (rfSource == "Diags")
794 {
795 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
796 }
797 else if (rfSource == "Cd")
798 {
799 bootSource =
800 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
801 }
802 else if (rfSource == "BiosSetup")
803 {
804 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530805 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700806 else if (rfSource == "Usb")
807 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700808 bootSource =
809 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700810 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530811 else
812 {
George Liu0fda0f12021-11-16 10:06:17 +0800813 BMCWEB_LOG_DEBUG
814 << "Invalid property value for BootSourceOverrideTarget: "
815 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700816 messages::propertyValueNotInList(aResp->res, rfSource,
817 "BootSourceTargetOverride");
818 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530819 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700820 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530821}
Ali Ahmed19817712021-06-29 17:01:52 -0500822
Andrew Geissler978b8802020-11-19 13:36:40 -0600823/**
824 * @brief Retrieves boot progress of the system
825 *
826 * @param[in] aResp Shared pointer for generating response message.
827 *
828 * @return None.
829 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800830inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600831{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700832 sdbusplus::asio::getProperty<std::string>(
833 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
834 "/xyz/openbmc_project/state/host0",
835 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600836 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700837 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600838 if (ec)
839 {
840 // BootProgress is an optional object so just do nothing if
841 // not found
842 return;
843 }
844
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700845 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600846
Andrew Geisslere43914b2022-01-06 13:59:39 -0600847 aResp->res.jsonValue["BootProgress"]["LastState"] =
848 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700849 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600850}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530851
852/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300853 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300854 *
855 * @param[in] aResp Shared pointer for generating response message.
856 *
857 * @return None.
858 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300859
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300860inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300861{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700862 sdbusplus::asio::getProperty<std::string>(
863 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
864 "/xyz/openbmc_project/control/host0/boot",
865 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700867 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868 if (ec)
869 {
870 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300871 return;
872 }
873
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700874 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300875
George Liu0fda0f12021-11-16 10:06:17 +0800876 aResp->res
877 .jsonValue["Boot"]
878 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
879 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300880
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700881 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882 if (rfType.empty())
883 {
884 messages::internalError(aResp->res);
885 return;
886 }
887
888 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700889 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300890}
891
892/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300893 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530894 *
895 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530896 *
897 * @return None.
898 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300899
900inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530901{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700902 sdbusplus::asio::getProperty<std::string>(
903 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
904 "/xyz/openbmc_project/control/host0/boot",
905 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300906 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700907 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908 if (ec)
909 {
910 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
911 messages::internalError(aResp->res);
912 return;
913 }
914
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700915 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530916
George Liu0fda0f12021-11-16 10:06:17 +0800917 aResp->res
918 .jsonValue["Boot"]
919 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
920 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530921
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700922 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
924 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700925 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530926 if (!rfMode.empty())
927 {
928 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
929 rfMode;
930 }
931 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700932 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933}
934
935/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300936 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530937 *
938 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530939 *
940 * @return None.
941 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300942
943inline void
944 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530945{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700946 sdbusplus::asio::getProperty<std::string>(
947 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
948 "/xyz/openbmc_project/control/host0/boot",
949 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300950 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700951 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530952 if (ec)
953 {
954 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
955 messages::internalError(aResp->res);
956 return;
957 }
958
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700959 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530960
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700961 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530962 if (!rfSource.empty())
963 {
964 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
965 rfSource;
966 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300967
968 // Get BootMode as BootSourceOverrideTarget is constructed
969 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300970 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700971 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530972}
973
974/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300975 * @brief This functions abstracts all the logic behind getting a
976 * "BootSourceOverrideEnabled" property from an overall boot override enable
977 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530978 *
979 * @param[in] aResp Shared pointer for generating response message.
980 *
981 * @return None.
982 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530983
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300984inline void
985 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
986 const bool bootOverrideEnableSetting)
987{
988 if (!bootOverrideEnableSetting)
989 {
990 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
991 return;
992 }
993
994 // If boot source override is enabled, we need to check 'one_time'
995 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700996 sdbusplus::asio::getProperty<bool>(
997 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
998 "/xyz/openbmc_project/control/host0/boot/one_time",
999 "xyz.openbmc_project.Object.Enable", "Enabled",
1000 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301001 if (ec)
1002 {
1003 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001004 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301005 return;
1006 }
1007
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001008 if (oneTimeSetting)
1009 {
1010 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1011 "Once";
1012 }
1013 else
1014 {
1015 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1016 "Continuous";
1017 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001018 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019}
1020
1021/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001022 * @brief Retrieves boot override enable over DBUS
1023 *
1024 * @param[in] aResp Shared pointer for generating response message.
1025 *
1026 * @return None.
1027 */
1028
1029inline void
1030 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1031{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001032 sdbusplus::asio::getProperty<bool>(
1033 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1034 "/xyz/openbmc_project/control/host0/boot",
1035 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001036 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001037 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001038 if (ec)
1039 {
1040 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1041 messages::internalError(aResp->res);
1042 return;
1043 }
1044
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001045 processBootOverrideEnable(aResp, bootOverrideEnable);
1046 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001047}
1048
1049/**
1050 * @brief Retrieves boot source override properties
1051 *
1052 * @param[in] aResp Shared pointer for generating response message.
1053 *
1054 * @return None.
1055 */
1056inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1057{
1058 BMCWEB_LOG_DEBUG << "Get boot information.";
1059
1060 getBootOverrideSource(aResp);
1061 getBootOverrideType(aResp);
1062 getBootOverrideEnable(aResp);
1063}
1064
1065/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001066 * @brief Retrieves the Last Reset Time
1067 *
1068 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1069 * and power off. Even though this is the "system" Redfish object look at the
1070 * chassis D-Bus interface for the LastStateChangeTime since this has the
1071 * last power operation time.
1072 *
1073 * @param[in] aResp Shared pointer for generating response message.
1074 *
1075 * @return None.
1076 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001077inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001078{
1079 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1080
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001081 sdbusplus::asio::getProperty<uint64_t>(
1082 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1083 "/xyz/openbmc_project/state/chassis0",
1084 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1085 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001086 if (ec)
1087 {
1088 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1089 return;
1090 }
1091
Gunnar Millsc0557e12020-06-30 11:26:20 -05001092 // LastStateChangeTime is epoch time, in milliseconds
1093 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001094 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001095
1096 // Convert to ISO 8601 standard
1097 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001098 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001099 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001100}
1101
1102/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001103 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1104 *
1105 * @param[in] aResp Shared pointer for generating response message.
1106 *
1107 * @return None.
1108 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001109inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001110{
1111 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1112
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001113 sdbusplus::asio::getProperty<bool>(
1114 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1115 "/xyz/openbmc_project/control/host0/auto_reboot",
1116 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1117 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001118 if (ec)
1119 {
1120 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1121 return;
1122 }
1123
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001124 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1125 if (autoRebootEnabled == true)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001126 {
1127 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1128 "RetryAttempts";
1129 // If AutomaticRetry (AutoReboot) is enabled see how many
1130 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001131 sdbusplus::asio::getProperty<uint32_t>(
1132 *crow::connections::systemBus,
1133 "xyz.openbmc_project.State.Host",
1134 "/xyz/openbmc_project/state/host0",
1135 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1136 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001137 [aResp](const boost::system::error_code ec2,
Ed Tanous914e2d52022-01-07 11:38:34 -08001138 const uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001139 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001140 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001141 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001142 return;
1143 }
1144
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001145 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001146 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001147
1148 aResp->res
1149 .jsonValue["Boot"]
1150 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001151 autoRebootAttemptsLeft;
1152 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001153 }
1154 else
1155 {
1156 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1157 "Disabled";
1158 }
1159
1160 // Not on D-Bus. Hardcoded here:
1161 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1162 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001163
1164 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1165 // and RetryAttempts. OpenBMC only supports Disabled and
1166 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001167 aResp->res
1168 .jsonValue["Boot"]
1169 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1170 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001171 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001172}
1173
1174/**
George Liuc6a620f2020-04-10 17:18:11 +08001175 * @brief Retrieves power restore policy over DBUS.
1176 *
1177 * @param[in] aResp Shared pointer for generating response message.
1178 *
1179 * @return None.
1180 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001181inline void
1182 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001183{
1184 BMCWEB_LOG_DEBUG << "Get power restore policy";
1185
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001186 sdbusplus::asio::getProperty<std::string>(
1187 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1188 "/xyz/openbmc_project/control/host0/power_restore_policy",
1189 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1190 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001191 if (ec)
1192 {
1193 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1194 return;
1195 }
1196
George Liu0fda0f12021-11-16 10:06:17 +08001197 const boost::container::flat_map<std::string, std::string> policyMaps = {
1198 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1199 "AlwaysOn"},
1200 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1201 "AlwaysOff"},
1202 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1203 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001204
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001205 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001206 if (policyMapsIt == policyMaps.end())
1207 {
1208 messages::internalError(aResp->res);
1209 return;
1210 }
1211
1212 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001213 });
George Liuc6a620f2020-04-10 17:18:11 +08001214}
1215
1216/**
Ali Ahmed19817712021-06-29 17:01:52 -05001217 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1218 * TPM is required for booting the host.
1219 *
1220 * @param[in] aResp Shared pointer for generating response message.
1221 *
1222 * @return None.
1223 */
1224inline void getTrustedModuleRequiredToBoot(
1225 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1226{
1227 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1228
1229 crow::connections::systemBus->async_method_call(
1230 [aResp](
1231 const boost::system::error_code ec,
1232 std::vector<std::pair<
1233 std::string,
1234 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1235 subtree) {
1236 if (ec)
1237 {
1238 BMCWEB_LOG_DEBUG
1239 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1240 // This is an optional D-Bus object so just return if
1241 // error occurs
1242 return;
1243 }
Ed Tanous26f69762022-01-25 09:49:11 -08001244 if (subtree.empty())
Ali Ahmed19817712021-06-29 17:01:52 -05001245 {
1246 // As noted above, this is an optional interface so just return
1247 // if there is no instance found
1248 return;
1249 }
1250
1251 /* When there is more than one TPMEnable object... */
1252 if (subtree.size() > 1)
1253 {
1254 BMCWEB_LOG_DEBUG
1255 << "DBUS response has more than 1 TPM Enable object:"
1256 << subtree.size();
1257 // Throw an internal Error and return
1258 messages::internalError(aResp->res);
1259 return;
1260 }
1261
1262 // Make sure the Dbus response map has a service and objectPath
1263 // field
1264 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1265 {
1266 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1267 messages::internalError(aResp->res);
1268 return;
1269 }
1270
1271 const std::string& path = subtree[0].first;
1272 const std::string& serv = subtree[0].second.begin()->first;
1273
1274 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001275 sdbusplus::asio::getProperty<bool>(
1276 *crow::connections::systemBus, serv, path,
1277 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1278 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001279 if (ec)
1280 {
1281 BMCWEB_LOG_DEBUG
1282 << "D-BUS response error on TPM.Policy Get" << ec;
1283 messages::internalError(aResp->res);
1284 return;
1285 }
1286
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001287 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001288 {
1289 aResp->res
1290 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1291 "Required";
1292 }
1293 else
1294 {
1295 aResp->res
1296 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1297 "Disabled";
1298 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001299 });
Ali Ahmed19817712021-06-29 17:01:52 -05001300 },
1301 "xyz.openbmc_project.ObjectMapper",
1302 "/xyz/openbmc_project/object_mapper",
1303 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1304 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1305}
1306
1307/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001308 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1309 * TPM is required for booting the host.
1310 *
1311 * @param[in] aResp Shared pointer for generating response message.
1312 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1313 *
1314 * @return None.
1315 */
1316inline void setTrustedModuleRequiredToBoot(
1317 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1318{
1319 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1320
1321 crow::connections::systemBus->async_method_call(
1322 [aResp, tpmRequired](
1323 const boost::system::error_code ec,
1324 std::vector<std::pair<
1325 std::string,
1326 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1327 subtree) {
1328 if (ec)
1329 {
1330 BMCWEB_LOG_DEBUG
1331 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1332 messages::internalError(aResp->res);
1333 return;
1334 }
Ed Tanous26f69762022-01-25 09:49:11 -08001335 if (subtree.empty())
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001336 {
1337 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1338 "TrustedModuleRequiredToBoot");
1339 return;
1340 }
1341
1342 /* When there is more than one TPMEnable object... */
1343 if (subtree.size() > 1)
1344 {
1345 BMCWEB_LOG_DEBUG
1346 << "DBUS response has more than 1 TPM Enable object:"
1347 << subtree.size();
1348 // Throw an internal Error and return
1349 messages::internalError(aResp->res);
1350 return;
1351 }
1352
1353 // Make sure the Dbus response map has a service and objectPath
1354 // field
1355 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1356 {
1357 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1358 messages::internalError(aResp->res);
1359 return;
1360 }
1361
1362 const std::string& path = subtree[0].first;
1363 const std::string& serv = subtree[0].second.begin()->first;
1364
1365 if (serv.empty())
1366 {
1367 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1368 messages::internalError(aResp->res);
1369 return;
1370 }
1371
1372 // Valid TPM Enable object found, now setting the value
1373 crow::connections::systemBus->async_method_call(
1374 [aResp](const boost::system::error_code ec) {
1375 if (ec)
1376 {
George Liu0fda0f12021-11-16 10:06:17 +08001377 BMCWEB_LOG_DEBUG
1378 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1379 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001380 messages::internalError(aResp->res);
1381 return;
1382 }
1383 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1384 },
1385 serv, path, "org.freedesktop.DBus.Properties", "Set",
1386 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001387 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001388 },
1389 "xyz.openbmc_project.ObjectMapper",
1390 "/xyz/openbmc_project/object_mapper",
1391 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1392 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1393}
1394
1395/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301396 * @brief Sets boot properties into DBUS object(s).
1397 *
1398 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001399 * @param[in] bootType The boot type to set.
1400 * @return Integer error code.
1401 */
1402inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001403 const std::optional<std::string>& bootType)
1404{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001405 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001406
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001407 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001408 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001409 return;
1410 }
1411
1412 // Source target specified
1413 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1414 // Figure out which DBUS interface and property to use
1415 if (*bootType == "Legacy")
1416 {
1417 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1418 }
1419 else if (*bootType == "UEFI")
1420 {
1421 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1422 }
1423 else
1424 {
1425 BMCWEB_LOG_DEBUG << "Invalid property value for "
1426 "BootSourceOverrideMode: "
1427 << *bootType;
1428 messages::propertyValueNotInList(aResp->res, *bootType,
1429 "BootSourceOverrideMode");
1430 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001431 }
1432
1433 // Act on validated parameters
1434 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1435
1436 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001437 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001438 if (ec)
1439 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001440 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1441 if (ec.value() == boost::asio::error::host_unreachable)
1442 {
1443 messages::resourceNotFound(aResp->res, "Set", "BootType");
1444 return;
1445 }
1446 messages::internalError(aResp->res);
1447 return;
1448 }
1449 BMCWEB_LOG_DEBUG << "Boot type update done.";
1450 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001451 "xyz.openbmc_project.Settings",
1452 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001453 "org.freedesktop.DBus.Properties", "Set",
1454 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001455 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001456}
1457
1458/**
1459 * @brief Sets boot properties into DBUS object(s).
1460 *
1461 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001462 * @param[in] bootType The boot type to set.
1463 * @return Integer error code.
1464 */
1465inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1466 const std::optional<std::string>& bootEnable)
1467{
1468 if (!bootEnable)
1469 {
1470 return;
1471 }
1472 // Source target specified
1473 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1474
1475 bool bootOverrideEnable = false;
1476 bool bootOverridePersistent = false;
1477 // Figure out which DBUS interface and property to use
1478 if (*bootEnable == "Disabled")
1479 {
1480 bootOverrideEnable = false;
1481 }
1482 else if (*bootEnable == "Once")
1483 {
1484 bootOverrideEnable = true;
1485 bootOverridePersistent = false;
1486 }
1487 else if (*bootEnable == "Continuous")
1488 {
1489 bootOverrideEnable = true;
1490 bootOverridePersistent = true;
1491 }
1492 else
1493 {
George Liu0fda0f12021-11-16 10:06:17 +08001494 BMCWEB_LOG_DEBUG
1495 << "Invalid property value for BootSourceOverrideEnabled: "
1496 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001497 messages::propertyValueNotInList(aResp->res, *bootEnable,
1498 "BootSourceOverrideEnabled");
1499 return;
1500 }
1501
1502 // Act on validated parameters
1503 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1504
1505 crow::connections::systemBus->async_method_call(
1506 [aResp](const boost::system::error_code ec) {
1507 if (ec)
1508 {
1509 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1510 messages::internalError(aResp->res);
1511 return;
1512 }
1513 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1514 },
1515 "xyz.openbmc_project.Settings",
1516 "/xyz/openbmc_project/control/host0/boot",
1517 "org.freedesktop.DBus.Properties", "Set",
1518 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001519 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001520
1521 if (!bootOverrideEnable)
1522 {
1523 return;
1524 }
1525
1526 // In case boot override is enabled we need to set correct value for the
1527 // 'one_time' enable DBus interface
1528 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1529 << bootOverridePersistent;
1530
1531 crow::connections::systemBus->async_method_call(
1532 [aResp](const boost::system::error_code ec) {
1533 if (ec)
1534 {
1535 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1536 messages::internalError(aResp->res);
1537 return;
1538 }
1539 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1540 },
1541 "xyz.openbmc_project.Settings",
1542 "/xyz/openbmc_project/control/host0/boot/one_time",
1543 "org.freedesktop.DBus.Properties", "Set",
1544 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001545 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001546}
1547
1548/**
1549 * @brief Sets boot properties into DBUS object(s).
1550 *
1551 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301552 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301553 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001554 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301555 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001556inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001557 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301558{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001559 std::string bootSourceStr;
1560 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001561
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001562 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301563 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001564 return;
1565 }
1566
1567 // Source target specified
1568 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1569 // Figure out which DBUS interface and property to use
1570 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1571 {
1572 BMCWEB_LOG_DEBUG
1573 << "Invalid property value for BootSourceOverrideTarget: "
1574 << *bootSource;
1575 messages::propertyValueNotInList(aResp->res, *bootSource,
1576 "BootSourceTargetOverride");
1577 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001578 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301579
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001580 // Act on validated parameters
1581 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1582 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001583
1584 crow::connections::systemBus->async_method_call(
1585 [aResp](const boost::system::error_code ec) {
1586 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301587 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001588 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1589 messages::internalError(aResp->res);
1590 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301591 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001592 BMCWEB_LOG_DEBUG << "Boot source update done.";
1593 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001594 "xyz.openbmc_project.Settings",
1595 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001596 "org.freedesktop.DBus.Properties", "Set",
1597 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001598 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001599
1600 crow::connections::systemBus->async_method_call(
1601 [aResp](const boost::system::error_code ec) {
1602 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301603 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001604 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1605 messages::internalError(aResp->res);
1606 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301607 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001608 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1609 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001610 "xyz.openbmc_project.Settings",
1611 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001612 "org.freedesktop.DBus.Properties", "Set",
1613 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001614 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001615}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001616
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001617/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001618 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301619 *
1620 * @param[in] aResp Shared pointer for generating response message.
1621 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001622 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301623 * @param[in] bootEnable The boot override enable from incoming RF request.
1624 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001625 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301626 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001627
1628inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1629 const std::optional<std::string>& bootSource,
1630 const std::optional<std::string>& bootType,
1631 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301632{
1633 BMCWEB_LOG_DEBUG << "Set boot information.";
1634
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001635 setBootModeOrSource(aResp, bootSource);
1636 setBootType(aResp, bootType);
1637 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301638}
1639
George Liuc6a620f2020-04-10 17:18:11 +08001640/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001641 * @brief Sets AssetTag
1642 *
1643 * @param[in] aResp Shared pointer for generating response message.
1644 * @param[in] assetTag "AssetTag" from request.
1645 *
1646 * @return None.
1647 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001648inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001649 const std::string& assetTag)
1650{
1651 crow::connections::systemBus->async_method_call(
1652 [aResp, assetTag](
1653 const boost::system::error_code ec,
1654 const std::vector<std::pair<
1655 std::string,
1656 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1657 subtree) {
1658 if (ec)
1659 {
1660 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1661 messages::internalError(aResp->res);
1662 return;
1663 }
Ed Tanous26f69762022-01-25 09:49:11 -08001664 if (subtree.empty())
Gunnar Mills98e386e2020-10-30 14:58:09 -05001665 {
1666 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1667 messages::internalError(aResp->res);
1668 return;
1669 }
1670 // Assume only 1 system D-Bus object
1671 // Throw an error if there is more than 1
1672 if (subtree.size() > 1)
1673 {
1674 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1675 messages::internalError(aResp->res);
1676 return;
1677 }
1678 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1679 {
1680 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1681 messages::internalError(aResp->res);
1682 return;
1683 }
1684
1685 const std::string& path = subtree[0].first;
1686 const std::string& service = subtree[0].second.begin()->first;
1687
1688 if (service.empty())
1689 {
1690 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1691 messages::internalError(aResp->res);
1692 return;
1693 }
1694
1695 crow::connections::systemBus->async_method_call(
1696 [aResp](const boost::system::error_code ec2) {
1697 if (ec2)
1698 {
1699 BMCWEB_LOG_DEBUG
1700 << "D-Bus response error on AssetTag Set " << ec2;
1701 messages::internalError(aResp->res);
1702 return;
1703 }
1704 },
1705 service, path, "org.freedesktop.DBus.Properties", "Set",
1706 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001707 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001708 },
1709 "xyz.openbmc_project.ObjectMapper",
1710 "/xyz/openbmc_project/object_mapper",
1711 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1712 "/xyz/openbmc_project/inventory", int32_t(0),
1713 std::array<const char*, 1>{
1714 "xyz.openbmc_project.Inventory.Item.System"});
1715}
1716
1717/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001718 * @brief Sets automaticRetry (Auto Reboot)
1719 *
1720 * @param[in] aResp Shared pointer for generating response message.
1721 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1722 *
1723 * @return None.
1724 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001725inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001726 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001727{
1728 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1729
1730 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001731 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001732
1733 if (automaticRetryConfig == "Disabled")
1734 {
1735 autoRebootEnabled = false;
1736 }
1737 else if (automaticRetryConfig == "RetryAttempts")
1738 {
1739 autoRebootEnabled = true;
1740 }
1741 else
1742 {
George Liu0fda0f12021-11-16 10:06:17 +08001743 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001744 << automaticRetryConfig;
1745 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1746 "AutomaticRetryConfig");
1747 return;
1748 }
1749
1750 crow::connections::systemBus->async_method_call(
1751 [aResp](const boost::system::error_code ec) {
1752 if (ec)
1753 {
1754 messages::internalError(aResp->res);
1755 return;
1756 }
1757 },
1758 "xyz.openbmc_project.Settings",
1759 "/xyz/openbmc_project/control/host0/auto_reboot",
1760 "org.freedesktop.DBus.Properties", "Set",
1761 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001762 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001763}
1764
1765/**
George Liuc6a620f2020-04-10 17:18:11 +08001766 * @brief Sets power restore policy properties.
1767 *
1768 * @param[in] aResp Shared pointer for generating response message.
1769 * @param[in] policy power restore policy properties from request.
1770 *
1771 * @return None.
1772 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001773inline void
1774 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1775 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001776{
1777 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1778
1779 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001780 {"AlwaysOn",
1781 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1782 {"AlwaysOff",
1783 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1784 {"LastState",
1785 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001786
1787 std::string powerRestorPolicy;
1788
Gunnar Mills4e69c902021-01-05 19:50:11 -06001789 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001790 if (policyMapsIt == policyMaps.end())
1791 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001792 messages::propertyValueNotInList(aResp->res, policy,
1793 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001794 return;
1795 }
1796
1797 powerRestorPolicy = policyMapsIt->second;
1798
1799 crow::connections::systemBus->async_method_call(
1800 [aResp](const boost::system::error_code ec) {
1801 if (ec)
1802 {
1803 messages::internalError(aResp->res);
1804 return;
1805 }
1806 },
1807 "xyz.openbmc_project.Settings",
1808 "/xyz/openbmc_project/control/host0/power_restore_policy",
1809 "org.freedesktop.DBus.Properties", "Set",
1810 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001811 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001812}
1813
AppaRao Pulia6349912019-10-18 17:16:08 +05301814#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1815/**
1816 * @brief Retrieves provisioning status
1817 *
1818 * @param[in] aResp Shared pointer for completing asynchronous calls.
1819 *
1820 * @return None.
1821 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001822inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301823{
1824 BMCWEB_LOG_DEBUG << "Get OEM information.";
1825 crow::connections::systemBus->async_method_call(
1826 [aResp](const boost::system::error_code ec,
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001827 const std::vector<
1828 std::pair<std::string, dbus::utility::DbusVariantType>>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001829 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301830 nlohmann::json& oemPFR =
1831 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001832 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1833 "#OemComputerSystem.OpenBmc";
1834 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1835
AppaRao Pulia6349912019-10-18 17:16:08 +05301836 if (ec)
1837 {
1838 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301839 // not an error, don't have to have the interface
1840 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301841 return;
1842 }
1843
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001844 const bool* provState = nullptr;
1845 const bool* lockState = nullptr;
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001846 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1847 property : propertiesList)
AppaRao Pulia6349912019-10-18 17:16:08 +05301848 {
1849 if (property.first == "UfmProvisioned")
1850 {
1851 provState = std::get_if<bool>(&property.second);
1852 }
1853 else if (property.first == "UfmLocked")
1854 {
1855 lockState = std::get_if<bool>(&property.second);
1856 }
1857 }
1858
1859 if ((provState == nullptr) || (lockState == nullptr))
1860 {
1861 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1862 messages::internalError(aResp->res);
1863 return;
1864 }
1865
AppaRao Pulia6349912019-10-18 17:16:08 +05301866 if (*provState == true)
1867 {
1868 if (*lockState == true)
1869 {
1870 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1871 }
1872 else
1873 {
1874 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1875 }
1876 }
1877 else
1878 {
1879 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1880 }
1881 },
1882 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1883 "org.freedesktop.DBus.Properties", "GetAll",
1884 "xyz.openbmc_project.PFR.Attributes");
1885}
1886#endif
1887
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301888/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001889 * @brief Translate the PowerMode to a response message.
1890 *
1891 * @param[in] aResp Shared pointer for generating response message.
1892 * @param[in] modeValue PowerMode value to be translated
1893 *
1894 * @return None.
1895 */
1896inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1897 const std::string& modeValue)
1898{
1899 std::string modeString;
1900
George Liu0fda0f12021-11-16 10:06:17 +08001901 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001902 {
1903 aResp->res.jsonValue["PowerMode"] = "Static";
1904 }
George Liu0fda0f12021-11-16 10:06:17 +08001905 else if (
1906 modeValue ==
1907 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001908 {
1909 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1910 }
George Liu0fda0f12021-11-16 10:06:17 +08001911 else if (modeValue ==
1912 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001913 {
1914 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1915 }
George Liu0fda0f12021-11-16 10:06:17 +08001916 else if (modeValue ==
1917 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001918 {
1919 aResp->res.jsonValue["PowerMode"] = "OEM";
1920 }
1921 else
1922 {
1923 // Any other values would be invalid
1924 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1925 messages::internalError(aResp->res);
1926 }
1927}
1928
1929/**
1930 * @brief Retrieves system power mode
1931 *
1932 * @param[in] aResp Shared pointer for generating response message.
1933 *
1934 * @return None.
1935 */
1936inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1937{
1938 BMCWEB_LOG_DEBUG << "Get power mode.";
1939
1940 // Get Power Mode object path:
1941 crow::connections::systemBus->async_method_call(
1942 [aResp](
1943 const boost::system::error_code ec,
1944 const std::vector<std::pair<
1945 std::string,
1946 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1947 subtree) {
1948 if (ec)
1949 {
1950 BMCWEB_LOG_DEBUG
1951 << "DBUS response error on Power.Mode GetSubTree " << ec;
1952 // This is an optional D-Bus object so just return if
1953 // error occurs
1954 return;
1955 }
1956 if (subtree.empty())
1957 {
1958 // As noted above, this is an optional interface so just return
1959 // if there is no instance found
1960 return;
1961 }
1962 if (subtree.size() > 1)
1963 {
1964 // More then one PowerMode object is not supported and is an
1965 // error
1966 BMCWEB_LOG_DEBUG
1967 << "Found more than 1 system D-Bus Power.Mode objects: "
1968 << subtree.size();
1969 messages::internalError(aResp->res);
1970 return;
1971 }
1972 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1973 {
1974 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1975 messages::internalError(aResp->res);
1976 return;
1977 }
1978 const std::string& path = subtree[0].first;
1979 const std::string& service = subtree[0].second.begin()->first;
1980 if (service.empty())
1981 {
1982 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1983 messages::internalError(aResp->res);
1984 return;
1985 }
1986 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001987 sdbusplus::asio::getProperty<std::string>(
1988 *crow::connections::systemBus, service, path,
1989 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001990 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001991 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001992 if (ec)
1993 {
1994 BMCWEB_LOG_DEBUG
1995 << "DBUS response error on PowerMode Get: " << ec;
1996 messages::internalError(aResp->res);
1997 return;
1998 }
1999
Chris Cain3a2d04242021-05-28 16:57:10 -05002000 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2001 {"Static", "MaximumPerformance", "PowerSaving"};
2002
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002003 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2004 translatePowerMode(aResp, pmode);
2005 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002006 },
2007 "xyz.openbmc_project.ObjectMapper",
2008 "/xyz/openbmc_project/object_mapper",
2009 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2010 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2011}
2012
2013/**
2014 * @brief Validate the specified mode is valid and return the PowerMode
2015 * name associated with that string
2016 *
2017 * @param[in] aResp Shared pointer for generating response message.
2018 * @param[in] modeString String representing the desired PowerMode
2019 *
2020 * @return PowerMode value or empty string if mode is not valid
2021 */
2022inline std::string
2023 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2024 const std::string& modeString)
2025{
2026 std::string mode;
2027
2028 if (modeString == "Static")
2029 {
2030 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2031 }
2032 else if (modeString == "MaximumPerformance")
2033 {
George Liu0fda0f12021-11-16 10:06:17 +08002034 mode =
2035 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002036 }
2037 else if (modeString == "PowerSaving")
2038 {
2039 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2040 }
2041 else
2042 {
2043 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2044 }
2045 return mode;
2046}
2047
2048/**
2049 * @brief Sets system power mode.
2050 *
2051 * @param[in] aResp Shared pointer for generating response message.
2052 * @param[in] pmode System power mode from request.
2053 *
2054 * @return None.
2055 */
2056inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2057 const std::string& pmode)
2058{
2059 BMCWEB_LOG_DEBUG << "Set power mode.";
2060
2061 std::string powerMode = validatePowerMode(aResp, pmode);
2062 if (powerMode.empty())
2063 {
2064 return;
2065 }
2066
2067 // Get Power Mode object path:
2068 crow::connections::systemBus->async_method_call(
2069 [aResp, powerMode](
2070 const boost::system::error_code ec,
2071 const std::vector<std::pair<
2072 std::string,
2073 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2074 subtree) {
2075 if (ec)
2076 {
2077 BMCWEB_LOG_DEBUG
2078 << "DBUS response error on Power.Mode GetSubTree " << ec;
2079 // This is an optional D-Bus object, but user attempted to patch
2080 messages::internalError(aResp->res);
2081 return;
2082 }
2083 if (subtree.empty())
2084 {
2085 // This is an optional D-Bus object, but user attempted to patch
2086 messages::resourceNotFound(aResp->res, "ComputerSystem",
2087 "PowerMode");
2088 return;
2089 }
2090 if (subtree.size() > 1)
2091 {
2092 // More then one PowerMode object is not supported and is an
2093 // error
2094 BMCWEB_LOG_DEBUG
2095 << "Found more than 1 system D-Bus Power.Mode objects: "
2096 << subtree.size();
2097 messages::internalError(aResp->res);
2098 return;
2099 }
2100 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2101 {
2102 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2103 messages::internalError(aResp->res);
2104 return;
2105 }
2106 const std::string& path = subtree[0].first;
2107 const std::string& service = subtree[0].second.begin()->first;
2108 if (service.empty())
2109 {
2110 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2111 messages::internalError(aResp->res);
2112 return;
2113 }
2114
2115 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2116 << path;
2117
2118 // Set the Power Mode property
2119 crow::connections::systemBus->async_method_call(
2120 [aResp](const boost::system::error_code ec) {
2121 if (ec)
2122 {
2123 messages::internalError(aResp->res);
2124 return;
2125 }
2126 },
2127 service, path, "org.freedesktop.DBus.Properties", "Set",
2128 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002129 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002130 },
2131 "xyz.openbmc_project.ObjectMapper",
2132 "/xyz/openbmc_project/object_mapper",
2133 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2134 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2135}
2136
2137/**
Yong Li51709ff2019-09-30 14:13:04 +08002138 * @brief Translates watchdog timeout action DBUS property value to redfish.
2139 *
2140 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2141 *
2142 * @return Returns as a string, the timeout action in Redfish terms. If
2143 * translation cannot be done, returns an empty string.
2144 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002145inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002146{
2147 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2148 {
2149 return "None";
2150 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002151 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002152 {
2153 return "ResetSystem";
2154 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002155 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002156 {
2157 return "PowerDown";
2158 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002159 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002160 {
2161 return "PowerCycle";
2162 }
2163
2164 return "";
2165}
2166
2167/**
Yong Lic45f0082019-10-10 14:19:01 +08002168 *@brief Translates timeout action from Redfish to DBUS property value.
2169 *
2170 *@param[in] rfAction The timeout action in Redfish.
2171 *
2172 *@return Returns as a string, the time_out action as expected by DBUS.
2173 *If translation cannot be done, returns an empty string.
2174 */
2175
Ed Tanous23a21a12020-07-25 04:45:05 +00002176inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002177{
2178 if (rfAction == "None")
2179 {
2180 return "xyz.openbmc_project.State.Watchdog.Action.None";
2181 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002182 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002183 {
2184 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2185 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002186 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002187 {
2188 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2189 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002190 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002191 {
2192 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2193 }
2194
2195 return "";
2196}
2197
2198/**
Yong Li51709ff2019-09-30 14:13:04 +08002199 * @brief Retrieves host watchdog timer properties over DBUS
2200 *
2201 * @param[in] aResp Shared pointer for completing asynchronous calls.
2202 *
2203 * @return None.
2204 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002205inline void
2206 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002207{
2208 BMCWEB_LOG_DEBUG << "Get host watchodg";
2209 crow::connections::systemBus->async_method_call(
2210 [aResp](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002211 const PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002212 if (ec)
2213 {
2214 // watchdog service is stopped
2215 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2216 return;
2217 }
2218
2219 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2220
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002221 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002222 aResp->res.jsonValue["HostWatchdogTimer"];
2223
2224 // watchdog service is running/enabled
2225 hostWatchdogTimer["Status"]["State"] = "Enabled";
2226
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002227 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002228 {
2229 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2230 if (property.first == "Enabled")
2231 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002232 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002233
2234 if (!state)
2235 {
2236 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002237 return;
Yong Li51709ff2019-09-30 14:13:04 +08002238 }
2239
2240 hostWatchdogTimer["FunctionEnabled"] = *state;
2241 }
2242 else if (property.first == "ExpireAction")
2243 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002244 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002245 std::get_if<std::string>(&property.second);
2246 if (!s)
2247 {
2248 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002249 return;
Yong Li51709ff2019-09-30 14:13:04 +08002250 }
2251
2252 std::string action = dbusToRfWatchdogAction(*s);
2253 if (action.empty())
2254 {
2255 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002256 return;
Yong Li51709ff2019-09-30 14:13:04 +08002257 }
2258 hostWatchdogTimer["TimeoutAction"] = action;
2259 }
2260 }
2261 },
2262 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2263 "org.freedesktop.DBus.Properties", "GetAll",
2264 "xyz.openbmc_project.State.Watchdog");
2265}
2266
2267/**
Yong Lic45f0082019-10-10 14:19:01 +08002268 * @brief Sets Host WatchDog Timer properties.
2269 *
2270 * @param[in] aResp Shared pointer for generating response message.
2271 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2272 * RF request.
2273 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2274 *
2275 * @return None.
2276 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002277inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002278 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002279 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002280{
2281 BMCWEB_LOG_DEBUG << "Set host watchdog";
2282
2283 if (wdtTimeOutAction)
2284 {
2285 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2286 // check if TimeOut Action is Valid
2287 if (wdtTimeOutActStr.empty())
2288 {
2289 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2290 << *wdtTimeOutAction;
2291 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2292 "TimeoutAction");
2293 return;
2294 }
2295
2296 crow::connections::systemBus->async_method_call(
2297 [aResp](const boost::system::error_code ec) {
2298 if (ec)
2299 {
2300 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2301 messages::internalError(aResp->res);
2302 return;
2303 }
2304 },
2305 "xyz.openbmc_project.Watchdog",
2306 "/xyz/openbmc_project/watchdog/host0",
2307 "org.freedesktop.DBus.Properties", "Set",
2308 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002309 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002310 }
2311
2312 if (wdtEnable)
2313 {
2314 crow::connections::systemBus->async_method_call(
2315 [aResp](const boost::system::error_code ec) {
2316 if (ec)
2317 {
2318 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2319 messages::internalError(aResp->res);
2320 return;
2321 }
2322 },
2323 "xyz.openbmc_project.Watchdog",
2324 "/xyz/openbmc_project/watchdog/host0",
2325 "org.freedesktop.DBus.Properties", "Set",
2326 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002327 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002328 }
2329}
2330
Chris Cain37bbf982021-09-20 10:53:09 -05002331using ipsPropertiesType =
2332 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2333/**
2334 * @brief Parse the Idle Power Saver properties into json
2335 *
2336 * @param[in] aResp Shared pointer for completing asynchronous calls.
2337 * @param[in] properties IPS property data from DBus.
2338 *
2339 * @return true if successful
2340 */
Ed Tanousf6674222021-11-13 09:41:41 -08002341inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2342 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002343{
2344 for (const auto& property : properties)
2345 {
2346 if (property.first == "Enabled")
2347 {
2348 const bool* state = std::get_if<bool>(&property.second);
2349 if (!state)
2350 {
2351 return false;
2352 }
2353 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2354 }
2355 else if (property.first == "EnterUtilizationPercent")
2356 {
2357 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2358 if (!util)
2359 {
2360 return false;
2361 }
2362 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2363 }
2364 else if (property.first == "EnterDwellTime")
2365 {
2366 // Convert Dbus time from milliseconds to seconds
2367 const uint64_t* timeMilliseconds =
2368 std::get_if<uint64_t>(&property.second);
2369 if (!timeMilliseconds)
2370 {
2371 return false;
2372 }
2373 const std::chrono::duration<uint64_t, std::milli> ms(
2374 *timeMilliseconds);
2375 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2376 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2377 .count();
2378 }
2379 else if (property.first == "ExitUtilizationPercent")
2380 {
2381 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2382 if (!util)
2383 {
2384 return false;
2385 }
2386 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2387 }
2388 else if (property.first == "ExitDwellTime")
2389 {
2390 // Convert Dbus time from milliseconds to seconds
2391 const uint64_t* timeMilliseconds =
2392 std::get_if<uint64_t>(&property.second);
2393 if (!timeMilliseconds)
2394 {
2395 return false;
2396 }
2397 const std::chrono::duration<uint64_t, std::milli> ms(
2398 *timeMilliseconds);
2399 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2400 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2401 .count();
2402 }
2403 else
2404 {
2405 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2406 << property.first;
2407 }
2408 }
2409
2410 return true;
2411}
2412
2413/**
2414 * @brief Retrieves host watchdog timer properties over DBUS
2415 *
2416 * @param[in] aResp Shared pointer for completing asynchronous calls.
2417 *
2418 * @return None.
2419 */
2420inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2421{
2422 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2423
2424 // Get IdlePowerSaver object path:
2425 crow::connections::systemBus->async_method_call(
2426 [aResp](
2427 const boost::system::error_code ec,
2428 const std::vector<std::pair<
2429 std::string,
2430 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2431 subtree) {
2432 if (ec)
2433 {
2434 BMCWEB_LOG_DEBUG
2435 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2436 << ec;
2437 messages::internalError(aResp->res);
2438 return;
2439 }
2440 if (subtree.empty())
2441 {
2442 // This is an optional interface so just return
2443 // if there is no instance found
2444 BMCWEB_LOG_DEBUG << "No instances found";
2445 return;
2446 }
2447 if (subtree.size() > 1)
2448 {
2449 // More then one PowerIdlePowerSaver object is not supported and
2450 // is an error
2451 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2452 "Power.IdlePowerSaver objects: "
2453 << subtree.size();
2454 messages::internalError(aResp->res);
2455 return;
2456 }
2457 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2458 {
2459 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2460 messages::internalError(aResp->res);
2461 return;
2462 }
2463 const std::string& path = subtree[0].first;
2464 const std::string& service = subtree[0].second.begin()->first;
2465 if (service.empty())
2466 {
2467 BMCWEB_LOG_DEBUG
2468 << "Power.IdlePowerSaver service mapper error!";
2469 messages::internalError(aResp->res);
2470 return;
2471 }
2472
2473 // Valid IdlePowerSaver object found, now read the current values
2474 crow::connections::systemBus->async_method_call(
2475 [aResp](const boost::system::error_code ec,
2476 ipsPropertiesType& properties) {
2477 if (ec)
2478 {
2479 BMCWEB_LOG_ERROR
2480 << "DBUS response error on IdlePowerSaver GetAll: "
2481 << ec;
2482 messages::internalError(aResp->res);
2483 return;
2484 }
2485
2486 if (parseIpsProperties(aResp, properties) == false)
2487 {
2488 messages::internalError(aResp->res);
2489 return;
2490 }
2491 },
2492 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2493 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2494 },
2495 "xyz.openbmc_project.ObjectMapper",
2496 "/xyz/openbmc_project/object_mapper",
2497 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2498 std::array<const char*, 1>{
2499 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2500
2501 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2502}
2503
2504/**
2505 * @brief Sets Idle Power Saver properties.
2506 *
2507 * @param[in] aResp Shared pointer for generating response message.
2508 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2509 * RF request.
2510 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2511 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2512 * before entering idle state.
2513 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2514 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2515 * before exiting idle state
2516 *
2517 * @return None.
2518 */
2519inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2520 const std::optional<bool> ipsEnable,
2521 const std::optional<uint8_t> ipsEnterUtil,
2522 const std::optional<uint64_t> ipsEnterTime,
2523 const std::optional<uint8_t> ipsExitUtil,
2524 const std::optional<uint64_t> ipsExitTime)
2525{
2526 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2527
2528 // Get IdlePowerSaver object path:
2529 crow::connections::systemBus->async_method_call(
2530 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2531 ipsExitTime](
2532 const boost::system::error_code ec,
2533 const std::vector<std::pair<
2534 std::string,
2535 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2536 subtree) {
2537 if (ec)
2538 {
2539 BMCWEB_LOG_DEBUG
2540 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2541 << ec;
2542 messages::internalError(aResp->res);
2543 return;
2544 }
2545 if (subtree.empty())
2546 {
2547 // This is an optional D-Bus object, but user attempted to patch
2548 messages::resourceNotFound(aResp->res, "ComputerSystem",
2549 "IdlePowerSaver");
2550 return;
2551 }
2552 if (subtree.size() > 1)
2553 {
2554 // More then one PowerIdlePowerSaver object is not supported and
2555 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002556 BMCWEB_LOG_DEBUG
2557 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2558 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002559 messages::internalError(aResp->res);
2560 return;
2561 }
2562 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2563 {
2564 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2565 messages::internalError(aResp->res);
2566 return;
2567 }
2568 const std::string& path = subtree[0].first;
2569 const std::string& service = subtree[0].second.begin()->first;
2570 if (service.empty())
2571 {
2572 BMCWEB_LOG_DEBUG
2573 << "Power.IdlePowerSaver service mapper error!";
2574 messages::internalError(aResp->res);
2575 return;
2576 }
2577
2578 // Valid Power IdlePowerSaver object found, now set any values that
2579 // need to be updated
2580
2581 if (ipsEnable)
2582 {
2583 crow::connections::systemBus->async_method_call(
2584 [aResp](const boost::system::error_code ec) {
2585 if (ec)
2586 {
2587 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2588 messages::internalError(aResp->res);
2589 return;
2590 }
2591 },
2592 service, path, "org.freedesktop.DBus.Properties", "Set",
2593 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002594 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002595 }
2596 if (ipsEnterUtil)
2597 {
2598 crow::connections::systemBus->async_method_call(
2599 [aResp](const boost::system::error_code ec) {
2600 if (ec)
2601 {
2602 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2603 messages::internalError(aResp->res);
2604 return;
2605 }
2606 },
2607 service, path, "org.freedesktop.DBus.Properties", "Set",
2608 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2609 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002610 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002611 }
2612 if (ipsEnterTime)
2613 {
2614 // Convert from seconds into milliseconds for DBus
2615 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2616 crow::connections::systemBus->async_method_call(
2617 [aResp](const boost::system::error_code ec) {
2618 if (ec)
2619 {
2620 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2621 messages::internalError(aResp->res);
2622 return;
2623 }
2624 },
2625 service, path, "org.freedesktop.DBus.Properties", "Set",
2626 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002627 "EnterDwellTime",
2628 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002629 }
2630 if (ipsExitUtil)
2631 {
2632 crow::connections::systemBus->async_method_call(
2633 [aResp](const boost::system::error_code ec) {
2634 if (ec)
2635 {
2636 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2637 messages::internalError(aResp->res);
2638 return;
2639 }
2640 },
2641 service, path, "org.freedesktop.DBus.Properties", "Set",
2642 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2643 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002644 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002645 }
2646 if (ipsExitTime)
2647 {
2648 // Convert from seconds into milliseconds for DBus
2649 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2650 crow::connections::systemBus->async_method_call(
2651 [aResp](const boost::system::error_code ec) {
2652 if (ec)
2653 {
2654 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2655 messages::internalError(aResp->res);
2656 return;
2657 }
2658 },
2659 service, path, "org.freedesktop.DBus.Properties", "Set",
2660 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002661 "ExitDwellTime",
2662 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002663 }
2664 },
2665 "xyz.openbmc_project.ObjectMapper",
2666 "/xyz/openbmc_project/object_mapper",
2667 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2668 std::array<const char*, 1>{
2669 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2670
2671 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2672}
2673
Yong Lic45f0082019-10-10 14:19:01 +08002674/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002675 * SystemsCollection derived class for delivering ComputerSystems Collection
2676 * Schema
2677 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002678inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002679{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002680 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002681 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002682 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002683 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002684 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2685 asyncResp->res.jsonValue["@odata.type"] =
2686 "#ComputerSystemCollection.ComputerSystemCollection";
2687 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2688 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002689
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002690 sdbusplus::asio::getProperty<std::string>(
2691 *crow::connections::systemBus,
2692 "xyz.openbmc_project.Settings",
2693 "/xyz/openbmc_project/network/hypervisor",
2694 "xyz.openbmc_project.Network.SystemConfiguration",
2695 "HostName",
2696 [asyncResp](const boost::system::error_code ec,
2697 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002698 nlohmann::json& ifaceArray =
2699 asyncResp->res.jsonValue["Members"];
2700 ifaceArray = nlohmann::json::array();
2701 auto& count =
2702 asyncResp->res.jsonValue["Members@odata.count"];
2703 ifaceArray.push_back(
2704 {{"@odata.id", "/redfish/v1/Systems/system"}});
2705 count = ifaceArray.size();
2706 if (!ec)
2707 {
2708 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2709 ifaceArray.push_back(
2710 {{"@odata.id",
2711 "/redfish/v1/Systems/hypervisor"}});
2712 count = ifaceArray.size();
2713 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002714 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002715 });
2716}
Sunitha Harish462023a2020-02-19 08:34:59 -06002717
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002718/**
2719 * Function transceives data with dbus directly.
2720 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002721inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002722{
2723 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2724 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2725 constexpr char const* interfaceName =
2726 "xyz.openbmc_project.Control.Host.NMI";
2727 constexpr char const* method = "NMI";
2728
2729 crow::connections::systemBus->async_method_call(
2730 [asyncResp](const boost::system::error_code ec) {
2731 if (ec)
2732 {
2733 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2734 messages::internalError(asyncResp->res);
2735 return;
2736 }
2737 messages::success(asyncResp->res);
2738 },
2739 serviceName, objectPath, interfaceName, method);
2740}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002741
2742/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002743 * SystemActionsReset class supports handle POST method for Reset action.
2744 * The class retrieves and sends data directly to D-Bus.
2745 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002746inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002747{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002748 /**
2749 * Function handles POST method request.
2750 * Analyzes POST body message before sends Reset request data to D-Bus.
2751 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002752 BMCWEB_ROUTE(app,
2753 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002754 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002755 .methods(
2756 boost::beast::http::verb::
2757 post)([](const crow::Request& req,
2758 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2759 std::string resetType;
2760 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2761 resetType))
2762 {
2763 return;
2764 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002765
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002766 // Get the command and host vs. chassis
2767 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002768 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002769 if ((resetType == "On") || (resetType == "ForceOn"))
2770 {
2771 command = "xyz.openbmc_project.State.Host.Transition.On";
2772 hostCommand = true;
2773 }
2774 else if (resetType == "ForceOff")
2775 {
2776 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2777 hostCommand = false;
2778 }
2779 else if (resetType == "ForceRestart")
2780 {
2781 command =
2782 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2783 hostCommand = true;
2784 }
2785 else if (resetType == "GracefulShutdown")
2786 {
2787 command = "xyz.openbmc_project.State.Host.Transition.Off";
2788 hostCommand = true;
2789 }
2790 else if (resetType == "GracefulRestart")
2791 {
George Liu0fda0f12021-11-16 10:06:17 +08002792 command =
2793 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002794 hostCommand = true;
2795 }
2796 else if (resetType == "PowerCycle")
2797 {
2798 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2799 hostCommand = true;
2800 }
2801 else if (resetType == "Nmi")
2802 {
2803 doNMI(asyncResp);
2804 return;
2805 }
2806 else
2807 {
2808 messages::actionParameterUnknown(asyncResp->res, "Reset",
2809 resetType);
2810 return;
2811 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002812
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002813 if (hostCommand)
2814 {
2815 crow::connections::systemBus->async_method_call(
2816 [asyncResp, resetType](const boost::system::error_code ec) {
2817 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002818 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2820 if (ec.value() ==
2821 boost::asio::error::invalid_argument)
2822 {
2823 messages::actionParameterNotSupported(
2824 asyncResp->res, resetType, "Reset");
2825 }
2826 else
2827 {
2828 messages::internalError(asyncResp->res);
2829 }
2830 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002831 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002832 messages::success(asyncResp->res);
2833 },
2834 "xyz.openbmc_project.State.Host",
2835 "/xyz/openbmc_project/state/host0",
2836 "org.freedesktop.DBus.Properties", "Set",
2837 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002838 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839 }
2840 else
2841 {
2842 crow::connections::systemBus->async_method_call(
2843 [asyncResp, resetType](const boost::system::error_code ec) {
2844 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002845 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002846 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2847 if (ec.value() ==
2848 boost::asio::error::invalid_argument)
2849 {
2850 messages::actionParameterNotSupported(
2851 asyncResp->res, resetType, "Reset");
2852 }
2853 else
2854 {
2855 messages::internalError(asyncResp->res);
2856 }
2857 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002858 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002859 messages::success(asyncResp->res);
2860 },
2861 "xyz.openbmc_project.State.Chassis",
2862 "/xyz/openbmc_project/state/chassis0",
2863 "org.freedesktop.DBus.Properties", "Set",
2864 "xyz.openbmc_project.State.Chassis",
2865 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002866 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002867 }
2868 });
2869}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002870
2871/**
Ed Tanous66173382018-08-15 18:20:59 -07002872 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002873 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002875{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002876
Ed Tanous1abe55e2018-09-05 08:30:59 -07002877 /**
2878 * Functions triggers appropriate requests on DBus
2879 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002880 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002881 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882 .methods(
2883 boost::beast::http::verb::
2884 get)([](const crow::Request&,
2885 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2886 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002887 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002888 asyncResp->res.jsonValue["Name"] = "system";
2889 asyncResp->res.jsonValue["Id"] = "system";
2890 asyncResp->res.jsonValue["SystemType"] = "Physical";
2891 asyncResp->res.jsonValue["Description"] = "Computer System";
2892 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2893 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2894 "Disabled";
2895 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2896 uint64_t(0);
2897 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2898 "Disabled";
2899 asyncResp->res.jsonValue["@odata.id"] =
2900 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002901
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002902 asyncResp->res.jsonValue["Processors"] = {
2903 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2904 asyncResp->res.jsonValue["Memory"] = {
2905 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2906 asyncResp->res.jsonValue["Storage"] = {
2907 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002908
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002909 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2910 {"target",
2911 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2912 {"@Redfish.ActionInfo",
2913 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002914
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002915 asyncResp->res.jsonValue["LogServices"] = {
2916 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002917
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002918 asyncResp->res.jsonValue["Bios"] = {
2919 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002920
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002921 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2922 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002923
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002924 asyncResp->res.jsonValue["Status"] = {
2925 {"Health", "OK"},
2926 {"State", "Enabled"},
2927 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002928
2929 // Fill in SerialConsole info
2930 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2931 15;
2932 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2933 {"ServiceEnabled", true},
2934 };
2935 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2936 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2937 {"ServiceEnabled", true},
2938 {"Port", 2200},
2939 // https://github.com/openbmc/docs/blob/master/console.md
2940 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2941 };
2942
2943#ifdef BMCWEB_ENABLE_KVM
2944 // Fill in GraphicalConsole info
2945 asyncResp->res.jsonValue["GraphicalConsole"] = {
2946 {"ServiceEnabled", true},
2947 {"MaxConcurrentSessions", 4},
2948 {"ConnectTypesSupported", {"KVMIP"}},
2949 };
2950#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002951 constexpr const std::array<const char*, 4> inventoryForSystems = {
2952 "xyz.openbmc_project.Inventory.Item.Dimm",
2953 "xyz.openbmc_project.Inventory.Item.Cpu",
2954 "xyz.openbmc_project.Inventory.Item.Drive",
2955 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002956
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002957 auto health = std::make_shared<HealthPopulate>(asyncResp);
2958 crow::connections::systemBus->async_method_call(
2959 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002960 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002961 if (ec)
2962 {
2963 // no inventory
2964 return;
2965 }
2966
Ed Tanous914e2d52022-01-07 11:38:34 -08002967 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002968 },
2969 "xyz.openbmc_project.ObjectMapper",
2970 "/xyz/openbmc_project/object_mapper",
2971 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2972 int32_t(0), inventoryForSystems);
2973
2974 health->populate();
2975
2976 getMainChassisId(
2977 asyncResp, [](const std::string& chassisId,
2978 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2979 aRsp->res.jsonValue["Links"]["Chassis"] = {
2980 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2981 });
2982
2983 getLocationIndicatorActive(asyncResp);
2984 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2985 getIndicatorLedState(asyncResp);
2986 getComputerSystem(asyncResp, health);
2987 getHostState(asyncResp);
2988 getBootProperties(asyncResp);
2989 getBootProgress(asyncResp);
2990 getPCIeDeviceList(asyncResp, "PCIeDevices");
2991 getHostWatchdogTimer(asyncResp);
2992 getPowerRestorePolicy(asyncResp);
2993 getAutomaticRetry(asyncResp);
2994 getLastResetTime(asyncResp);
2995#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2996 getProvisioningStatus(asyncResp);
2997#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002998 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002999 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003000 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003001 });
3002 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003003 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003004 .methods(boost::beast::http::verb::patch)(
3005 [](const crow::Request& req,
3006 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3007 std::optional<bool> locationIndicatorActive;
3008 std::optional<std::string> indicatorLed;
3009 std::optional<nlohmann::json> bootProps;
3010 std::optional<nlohmann::json> wdtTimerProps;
3011 std::optional<std::string> assetTag;
3012 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003013 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003014 std::optional<nlohmann::json> ipsProps;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003015 if (!json_util::readJson(
3016 req, asyncResp->res, "IndicatorLED", indicatorLed,
3017 "LocationIndicatorActive", locationIndicatorActive,
3018 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3019 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003020 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3021 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003022 {
James Feistb49ac872019-05-21 15:12:01 -07003023 return;
3024 }
3025
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003026 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003027
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003028 if (assetTag)
3029 {
3030 setAssetTag(asyncResp, *assetTag);
3031 }
James Feistb49ac872019-05-21 15:12:01 -07003032
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003033 if (wdtTimerProps)
3034 {
3035 std::optional<bool> wdtEnable;
3036 std::optional<std::string> wdtTimeOutAction;
3037
3038 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3039 "FunctionEnabled", wdtEnable,
3040 "TimeoutAction", wdtTimeOutAction))
3041 {
3042 return;
3043 }
3044 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3045 }
3046
3047 if (bootProps)
3048 {
3049 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003050 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003051 std::optional<std::string> bootEnable;
3052 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003053 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003054
3055 if (!json_util::readJson(
3056 *bootProps, asyncResp->res,
3057 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003058 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003059 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003060 "AutomaticRetryConfig", automaticRetryConfig,
3061 "TrustedModuleRequiredToBoot",
3062 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003063 {
3064 return;
3065 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003066
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003067 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003068 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003069 setBootProperties(asyncResp, bootSource, bootType,
3070 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003071 }
3072 if (automaticRetryConfig)
3073 {
3074 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3075 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003076
3077 if (trustedModuleRequiredToBoot)
3078 {
3079 setTrustedModuleRequiredToBoot(
3080 asyncResp, *trustedModuleRequiredToBoot);
3081 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003082 }
3083
3084 if (locationIndicatorActive)
3085 {
3086 setLocationIndicatorActive(asyncResp,
3087 *locationIndicatorActive);
3088 }
3089
3090 // TODO (Gunnar): Remove IndicatorLED after enough time has
3091 // passed
3092 if (indicatorLed)
3093 {
3094 setIndicatorLedState(asyncResp, *indicatorLed);
3095 asyncResp->res.addHeader(
3096 boost::beast::http::field::warning,
3097 "299 - \"IndicatorLED is deprecated. Use "
3098 "LocationIndicatorActive instead.\"");
3099 }
3100
3101 if (powerRestorePolicy)
3102 {
3103 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3104 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003105
3106 if (powerMode)
3107 {
3108 setPowerMode(asyncResp, *powerMode);
3109 }
Chris Cain37bbf982021-09-20 10:53:09 -05003110
3111 if (ipsProps)
3112 {
3113 std::optional<bool> ipsEnable;
3114 std::optional<uint8_t> ipsEnterUtil;
3115 std::optional<uint64_t> ipsEnterTime;
3116 std::optional<uint8_t> ipsExitUtil;
3117 std::optional<uint64_t> ipsExitTime;
3118
3119 if (!json_util::readJson(
3120 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3121 "EnterUtilizationPercent", ipsEnterUtil,
3122 "EnterDwellTimeSeconds", ipsEnterTime,
3123 "ExitUtilizationPercent", ipsExitUtil,
3124 "ExitDwellTimeSeconds", ipsExitTime))
3125 {
3126 return;
3127 }
3128 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3129 ipsEnterTime, ipsExitUtil, ipsExitTime);
3130 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003131 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003132}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303133
3134/**
3135 * SystemResetActionInfo derived class for delivering Computer Systems
3136 * ResetType AllowableValues using ResetInfo schema.
3137 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003138inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303139{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303140
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303141 /**
3142 * Functions triggers appropriate requests on DBus
3143 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003144 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003145 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003146 .methods(boost::beast::http::verb::get)(
3147 [](const crow::Request&,
3148 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3149 asyncResp->res.jsonValue = {
3150 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3151 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3152 {"Name", "Reset Action Info"},
3153 {"Id", "ResetActionInfo"},
3154 {"Parameters",
3155 {{{"Name", "ResetType"},
3156 {"Required", true},
3157 {"DataType", "String"},
3158 {"AllowableValues",
3159 {"On", "ForceOff", "ForceOn", "ForceRestart",
3160 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3161 "Nmi"}}}}}};
3162 });
3163}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003164} // namespace redfish