blob: d6805374d3331dbcf065ea1bceef9e0b3d7400ad [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
23
John Edward Broadbent7e860f12021-04-08 15:57:16 -070024#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070025#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080026#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070027#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070028#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060029#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050031
Ed Tanousabf2add2019-01-22 16:40:12 -080032#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034namespace redfish
35{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020036
Alpana Kumari9d3ae102019-04-12 06:49:32 -050037/**
38 * @brief Updates the Functional State of DIMMs
39 *
40 * @param[in] aResp Shared pointer for completing asynchronous calls
41 * @param[in] dimmState Dimm's Functional state, true/false
42 *
43 * @return None.
44 */
zhanghch058d1b46d2021-04-01 11:18:24 +080045inline void
46 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070047 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070049 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050
Gunnar Mills4e0453b2020-07-08 14:00:30 -050051 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052 // Update STATE only if previous State was DISABLED and current Dimm is
53 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050054 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
56 if (prevMemSummary == "Disabled")
57 {
Ed Tanouse05aec52022-01-25 10:28:56 -080058 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 {
60 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
61 "Enabled";
62 }
63 }
64}
65
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050066/*
67 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
68 *
69 * @param[in] aResp Shared pointer for completing asynchronous calls
70 * @param[in] cpuPresenceState CPU present or not
71 *
72 * @return None.
73 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074inline void
75 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
76 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070078 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079
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 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800117 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 {
119 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
120 "Enabled";
121 }
122 }
123}
124
Ali Ahmed03fbed92021-09-03 02:33:43 -0500125inline void getProcessorProperties(
126 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
127 const std::string& path,
Ed Tanous168e20c2021-12-13 14:39:53 -0800128 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
Ali Ahmed03fbed92021-09-03 02:33:43 -0500129 properties)
130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
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 {
Andrew Geissler22228c22022-01-31 13:55:33 -0600557 if (ec == boost::system::errc::host_unreachable)
558 {
559 // Service not available, no error, just don't return
560 // host state info
561 BMCWEB_LOG_DEBUG << "Service not available " << ec;
562 return;
563 }
564 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700565 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 return;
567 }
Ed Tanous66173382018-08-15 18:20:59 -0700568
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700569 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
570 // Verify Host State
571 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700572 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700573 aResp->res.jsonValue["PowerState"] = "On";
574 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700575 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700576 else if (hostState ==
577 "xyz.openbmc_project.State.Host.HostState.Quiesced")
578 {
579 aResp->res.jsonValue["PowerState"] = "On";
580 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
581 }
582 else if (hostState ==
583 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
584 {
585 aResp->res.jsonValue["PowerState"] = "On";
586 aResp->res.jsonValue["Status"]["State"] = "InTest";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOn";
593 aResp->res.jsonValue["Status"]["State"] = "Starting";
594 }
595 else if (
596 hostState ==
597 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
598 {
599 aResp->res.jsonValue["PowerState"] = "PoweringOff";
600 aResp->res.jsonValue["Status"]["State"] = "Disabled";
601 }
602 else
603 {
604 aResp->res.jsonValue["PowerState"] = "Off";
605 aResp->res.jsonValue["Status"]["State"] = "Disabled";
606 }
607 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700608}
609
610/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500611 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530612 *
613 * @param[in] dbusSource The boot source in DBUS speak.
614 *
615 * @return Returns as a string, the boot source in Redfish terms. If translation
616 * cannot be done, returns an empty string.
617 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000618inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530619{
620 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
621 {
622 return "None";
623 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700624 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530625 {
626 return "Hdd";
627 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700628 if (dbusSource ==
629 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 {
631 return "Cd";
632 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700633 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530634 {
635 return "Pxe";
636 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700637 if (dbusSource ==
638 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700639 {
640 return "Usb";
641 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700642 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530643}
644
645/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300646 * @brief Translates boot type DBUS property value to redfish.
647 *
648 * @param[in] dbusType The boot type in DBUS speak.
649 *
650 * @return Returns as a string, the boot type in Redfish terms. If translation
651 * cannot be done, returns an empty string.
652 */
653inline std::string dbusToRfBootType(const std::string& dbusType)
654{
655 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
656 {
657 return "Legacy";
658 }
659 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
660 {
661 return "UEFI";
662 }
663 return "";
664}
665
666/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500667 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668 *
669 * @param[in] dbusMode The boot mode in DBUS speak.
670 *
671 * @return Returns as a string, the boot mode in Redfish terms. If translation
672 * cannot be done, returns an empty string.
673 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000674inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530675{
676 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
677 {
678 return "None";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "Diags";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685 {
686 return "BiosSetup";
687 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700688 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530689}
690
691/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600692 * @brief Translates boot progress DBUS property value to redfish.
693 *
694 * @param[in] dbusBootProgress The boot progress in DBUS speak.
695 *
696 * @return Returns as a string, the boot progress in Redfish terms. If
697 * translation cannot be done, returns "None".
698 */
699inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
700{
701 // Now convert the D-Bus BootProgress to the appropriate Redfish
702 // enum
703 std::string rfBpLastState = "None";
704 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
705 "ProgressStages.Unspecified")
706 {
707 rfBpLastState = "None";
708 }
709 else if (dbusBootProgress ==
710 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
711 "PrimaryProcInit")
712 {
713 rfBpLastState = "PrimaryProcessorInitializationStarted";
714 }
715 else if (dbusBootProgress ==
716 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
717 "BusInit")
718 {
719 rfBpLastState = "BusInitializationStarted";
720 }
721 else if (dbusBootProgress ==
722 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
723 "MemoryInit")
724 {
725 rfBpLastState = "MemoryInitializationStarted";
726 }
727 else if (dbusBootProgress ==
728 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
729 "SecondaryProcInit")
730 {
731 rfBpLastState = "SecondaryProcessorInitializationStarted";
732 }
733 else if (dbusBootProgress ==
734 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
735 "PCIInit")
736 {
737 rfBpLastState = "PCIResourceConfigStarted";
738 }
739 else if (dbusBootProgress ==
740 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
741 "SystemSetup")
742 {
743 rfBpLastState = "SetupEntered";
744 }
745 else if (dbusBootProgress ==
746 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
747 "SystemInitComplete")
748 {
749 rfBpLastState = "SystemHardwareInitializationComplete";
750 }
751 else if (dbusBootProgress ==
752 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
753 "OSStart")
754 {
755 rfBpLastState = "OSBootStarted";
756 }
757 else if (dbusBootProgress ==
758 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
759 "OSRunning")
760 {
761 rfBpLastState = "OSRunning";
762 }
763 else
764 {
765 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
766 << dbusBootProgress;
767 // Just return the default
768 }
769 return rfBpLastState;
770}
771
772/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500773 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 *
775 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 * @param[out] bootSource The DBus source
777 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800781inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500782 const std::string& rfSource,
783 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300785 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
786 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788 if (rfSource == "None")
789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700792 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530793 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
795 }
796 else if (rfSource == "Hdd")
797 {
798 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
799 }
800 else if (rfSource == "Diags")
801 {
802 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
803 }
804 else if (rfSource == "Cd")
805 {
806 bootSource =
807 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
808 }
809 else if (rfSource == "BiosSetup")
810 {
811 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530812 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 else if (rfSource == "Usb")
814 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700815 bootSource =
816 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700817 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818 else
819 {
George Liu0fda0f12021-11-16 10:06:17 +0800820 BMCWEB_LOG_DEBUG
821 << "Invalid property value for BootSourceOverrideTarget: "
822 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 messages::propertyValueNotInList(aResp->res, rfSource,
824 "BootSourceTargetOverride");
825 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530826 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700827 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828}
Ali Ahmed19817712021-06-29 17:01:52 -0500829
Andrew Geissler978b8802020-11-19 13:36:40 -0600830/**
831 * @brief Retrieves boot progress of the system
832 *
833 * @param[in] aResp Shared pointer for generating response message.
834 *
835 * @return None.
836 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800837inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600838{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700839 sdbusplus::asio::getProperty<std::string>(
840 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
841 "/xyz/openbmc_project/state/host0",
842 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600843 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700844 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600845 if (ec)
846 {
847 // BootProgress is an optional object so just do nothing if
848 // not found
849 return;
850 }
851
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700852 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600853
Andrew Geisslere43914b2022-01-06 13:59:39 -0600854 aResp->res.jsonValue["BootProgress"]["LastState"] =
855 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700856 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600857}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530858
859/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300860 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300861 *
862 * @param[in] aResp Shared pointer for generating response message.
863 *
864 * @return None.
865 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300867inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700869 sdbusplus::asio::getProperty<std::string>(
870 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
871 "/xyz/openbmc_project/control/host0/boot",
872 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300873 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700874 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300875 if (ec)
876 {
877 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300878 return;
879 }
880
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700881 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882
George Liu0fda0f12021-11-16 10:06:17 +0800883 aResp->res
884 .jsonValue["Boot"]
885 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
886 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300887
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700888 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300889 if (rfType.empty())
890 {
891 messages::internalError(aResp->res);
892 return;
893 }
894
895 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700896 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300897}
898
899/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300900 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530901 *
902 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530903 *
904 * @return None.
905 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300906
907inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700909 sdbusplus::asio::getProperty<std::string>(
910 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
911 "/xyz/openbmc_project/control/host0/boot",
912 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300913 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700914 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 if (ec)
916 {
917 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
918 messages::internalError(aResp->res);
919 return;
920 }
921
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700922 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923
George Liu0fda0f12021-11-16 10:06:17 +0800924 aResp->res
925 .jsonValue["Boot"]
926 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
927 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530928
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700929 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530930 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
931 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700932 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933 if (!rfMode.empty())
934 {
935 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
936 rfMode;
937 }
938 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700939 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940}
941
942/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
945 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530946 *
947 * @return None.
948 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300949
950inline void
951 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530952{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700953 sdbusplus::asio::getProperty<std::string>(
954 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
955 "/xyz/openbmc_project/control/host0/boot",
956 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300957 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700958 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 if (ec)
960 {
961 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
962 messages::internalError(aResp->res);
963 return;
964 }
965
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700966 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700968 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969 if (!rfSource.empty())
970 {
971 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
972 rfSource;
973 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300974
975 // Get BootMode as BootSourceOverrideTarget is constructed
976 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300977 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700978 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530979}
980
981/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300982 * @brief This functions abstracts all the logic behind getting a
983 * "BootSourceOverrideEnabled" property from an overall boot override enable
984 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985 *
986 * @param[in] aResp Shared pointer for generating response message.
987 *
988 * @return None.
989 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300991inline void
992 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
993 const bool bootOverrideEnableSetting)
994{
995 if (!bootOverrideEnableSetting)
996 {
997 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
998 return;
999 }
1000
1001 // If boot source override is enabled, we need to check 'one_time'
1002 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001003 sdbusplus::asio::getProperty<bool>(
1004 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1005 "/xyz/openbmc_project/control/host0/boot/one_time",
1006 "xyz.openbmc_project.Object.Enable", "Enabled",
1007 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008 if (ec)
1009 {
1010 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001011 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301012 return;
1013 }
1014
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001015 if (oneTimeSetting)
1016 {
1017 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1018 "Once";
1019 }
1020 else
1021 {
1022 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1023 "Continuous";
1024 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001025 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026}
1027
1028/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029 * @brief Retrieves boot override enable over DBUS
1030 *
1031 * @param[in] aResp Shared pointer for generating response message.
1032 *
1033 * @return None.
1034 */
1035
1036inline void
1037 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1038{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001039 sdbusplus::asio::getProperty<bool>(
1040 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1041 "/xyz/openbmc_project/control/host0/boot",
1042 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001044 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001045 if (ec)
1046 {
1047 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1048 messages::internalError(aResp->res);
1049 return;
1050 }
1051
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001052 processBootOverrideEnable(aResp, bootOverrideEnable);
1053 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001054}
1055
1056/**
1057 * @brief Retrieves boot source override properties
1058 *
1059 * @param[in] aResp Shared pointer for generating response message.
1060 *
1061 * @return None.
1062 */
1063inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1064{
1065 BMCWEB_LOG_DEBUG << "Get boot information.";
1066
1067 getBootOverrideSource(aResp);
1068 getBootOverrideType(aResp);
1069 getBootOverrideEnable(aResp);
1070}
1071
1072/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001073 * @brief Retrieves the Last Reset Time
1074 *
1075 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1076 * and power off. Even though this is the "system" Redfish object look at the
1077 * chassis D-Bus interface for the LastStateChangeTime since this has the
1078 * last power operation time.
1079 *
1080 * @param[in] aResp Shared pointer for generating response message.
1081 *
1082 * @return None.
1083 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001084inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001085{
1086 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1087
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001088 sdbusplus::asio::getProperty<uint64_t>(
1089 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1090 "/xyz/openbmc_project/state/chassis0",
1091 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1092 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001093 if (ec)
1094 {
1095 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1096 return;
1097 }
1098
Gunnar Millsc0557e12020-06-30 11:26:20 -05001099 // LastStateChangeTime is epoch time, in milliseconds
1100 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001101 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001102
1103 // Convert to ISO 8601 standard
1104 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001105 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001106 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001107}
1108
1109/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001110 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1111 *
1112 * @param[in] aResp Shared pointer for generating response message.
1113 *
1114 * @return None.
1115 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001116inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001117{
1118 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1119
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001120 sdbusplus::asio::getProperty<bool>(
1121 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1122 "/xyz/openbmc_project/control/host0/auto_reboot",
1123 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1124 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001125 if (ec)
1126 {
1127 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1128 return;
1129 }
1130
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001131 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
Ed Tanouse05aec52022-01-25 10:28:56 -08001132 if (autoRebootEnabled)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001133 {
1134 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1135 "RetryAttempts";
1136 // If AutomaticRetry (AutoReboot) is enabled see how many
1137 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001138 sdbusplus::asio::getProperty<uint32_t>(
1139 *crow::connections::systemBus,
1140 "xyz.openbmc_project.State.Host",
1141 "/xyz/openbmc_project/state/host0",
1142 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1143 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001144 [aResp](const boost::system::error_code ec2,
Ed Tanous914e2d52022-01-07 11:38:34 -08001145 const uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001146 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001147 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001148 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001149 return;
1150 }
1151
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001152 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001153 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001154
1155 aResp->res
1156 .jsonValue["Boot"]
1157 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001158 autoRebootAttemptsLeft;
1159 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001160 }
1161 else
1162 {
1163 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1164 "Disabled";
1165 }
1166
1167 // Not on D-Bus. Hardcoded here:
1168 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1169 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001170
1171 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1172 // and RetryAttempts. OpenBMC only supports Disabled and
1173 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001174 aResp->res
1175 .jsonValue["Boot"]
1176 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1177 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001178 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001179}
1180
1181/**
George Liuc6a620f2020-04-10 17:18:11 +08001182 * @brief Retrieves power restore policy over DBUS.
1183 *
1184 * @param[in] aResp Shared pointer for generating response message.
1185 *
1186 * @return None.
1187 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001188inline void
1189 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001190{
1191 BMCWEB_LOG_DEBUG << "Get power restore policy";
1192
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001193 sdbusplus::asio::getProperty<std::string>(
1194 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1195 "/xyz/openbmc_project/control/host0/power_restore_policy",
1196 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1197 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001198 if (ec)
1199 {
1200 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1201 return;
1202 }
1203
George Liu0fda0f12021-11-16 10:06:17 +08001204 const boost::container::flat_map<std::string, std::string> policyMaps = {
1205 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1206 "AlwaysOn"},
1207 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1208 "AlwaysOff"},
1209 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1210 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001211
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001212 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001213 if (policyMapsIt == policyMaps.end())
1214 {
1215 messages::internalError(aResp->res);
1216 return;
1217 }
1218
1219 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001220 });
George Liuc6a620f2020-04-10 17:18:11 +08001221}
1222
1223/**
Ali Ahmed19817712021-06-29 17:01:52 -05001224 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1225 * TPM is required for booting the host.
1226 *
1227 * @param[in] aResp Shared pointer for generating response message.
1228 *
1229 * @return None.
1230 */
1231inline void getTrustedModuleRequiredToBoot(
1232 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1233{
1234 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1235
1236 crow::connections::systemBus->async_method_call(
1237 [aResp](
1238 const boost::system::error_code ec,
1239 std::vector<std::pair<
1240 std::string,
1241 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1242 subtree) {
1243 if (ec)
1244 {
1245 BMCWEB_LOG_DEBUG
1246 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1247 // This is an optional D-Bus object so just return if
1248 // error occurs
1249 return;
1250 }
Ed Tanous26f69762022-01-25 09:49:11 -08001251 if (subtree.empty())
Ali Ahmed19817712021-06-29 17:01:52 -05001252 {
1253 // As noted above, this is an optional interface so just return
1254 // if there is no instance found
1255 return;
1256 }
1257
1258 /* When there is more than one TPMEnable object... */
1259 if (subtree.size() > 1)
1260 {
1261 BMCWEB_LOG_DEBUG
1262 << "DBUS response has more than 1 TPM Enable object:"
1263 << subtree.size();
1264 // Throw an internal Error and return
1265 messages::internalError(aResp->res);
1266 return;
1267 }
1268
1269 // Make sure the Dbus response map has a service and objectPath
1270 // field
1271 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1272 {
1273 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1274 messages::internalError(aResp->res);
1275 return;
1276 }
1277
1278 const std::string& path = subtree[0].first;
1279 const std::string& serv = subtree[0].second.begin()->first;
1280
1281 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001282 sdbusplus::asio::getProperty<bool>(
1283 *crow::connections::systemBus, serv, path,
1284 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1285 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001286 if (ec)
1287 {
1288 BMCWEB_LOG_DEBUG
1289 << "D-BUS response error on TPM.Policy Get" << ec;
1290 messages::internalError(aResp->res);
1291 return;
1292 }
1293
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001294 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001295 {
1296 aResp->res
1297 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1298 "Required";
1299 }
1300 else
1301 {
1302 aResp->res
1303 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1304 "Disabled";
1305 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001306 });
Ali Ahmed19817712021-06-29 17:01:52 -05001307 },
1308 "xyz.openbmc_project.ObjectMapper",
1309 "/xyz/openbmc_project/object_mapper",
1310 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1311 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1312}
1313
1314/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001315 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1316 * TPM is required for booting the host.
1317 *
1318 * @param[in] aResp Shared pointer for generating response message.
1319 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1320 *
1321 * @return None.
1322 */
1323inline void setTrustedModuleRequiredToBoot(
1324 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1325{
1326 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1327
1328 crow::connections::systemBus->async_method_call(
1329 [aResp, tpmRequired](
1330 const boost::system::error_code ec,
1331 std::vector<std::pair<
1332 std::string,
1333 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1334 subtree) {
1335 if (ec)
1336 {
1337 BMCWEB_LOG_DEBUG
1338 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1339 messages::internalError(aResp->res);
1340 return;
1341 }
Ed Tanous26f69762022-01-25 09:49:11 -08001342 if (subtree.empty())
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001343 {
1344 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1345 "TrustedModuleRequiredToBoot");
1346 return;
1347 }
1348
1349 /* When there is more than one TPMEnable object... */
1350 if (subtree.size() > 1)
1351 {
1352 BMCWEB_LOG_DEBUG
1353 << "DBUS response has more than 1 TPM Enable object:"
1354 << subtree.size();
1355 // Throw an internal Error and return
1356 messages::internalError(aResp->res);
1357 return;
1358 }
1359
1360 // Make sure the Dbus response map has a service and objectPath
1361 // field
1362 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1363 {
1364 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1365 messages::internalError(aResp->res);
1366 return;
1367 }
1368
1369 const std::string& path = subtree[0].first;
1370 const std::string& serv = subtree[0].second.begin()->first;
1371
1372 if (serv.empty())
1373 {
1374 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1375 messages::internalError(aResp->res);
1376 return;
1377 }
1378
1379 // Valid TPM Enable object found, now setting the value
1380 crow::connections::systemBus->async_method_call(
1381 [aResp](const boost::system::error_code ec) {
1382 if (ec)
1383 {
George Liu0fda0f12021-11-16 10:06:17 +08001384 BMCWEB_LOG_DEBUG
1385 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1386 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001387 messages::internalError(aResp->res);
1388 return;
1389 }
1390 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1391 },
1392 serv, path, "org.freedesktop.DBus.Properties", "Set",
1393 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001394 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001395 },
1396 "xyz.openbmc_project.ObjectMapper",
1397 "/xyz/openbmc_project/object_mapper",
1398 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1399 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1400}
1401
1402/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301403 * @brief Sets boot properties into DBUS object(s).
1404 *
1405 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001406 * @param[in] bootType The boot type to set.
1407 * @return Integer error code.
1408 */
1409inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001410 const std::optional<std::string>& bootType)
1411{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001412 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001413
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001414 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001415 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001416 return;
1417 }
1418
1419 // Source target specified
1420 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1421 // Figure out which DBUS interface and property to use
1422 if (*bootType == "Legacy")
1423 {
1424 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1425 }
1426 else if (*bootType == "UEFI")
1427 {
1428 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1429 }
1430 else
1431 {
1432 BMCWEB_LOG_DEBUG << "Invalid property value for "
1433 "BootSourceOverrideMode: "
1434 << *bootType;
1435 messages::propertyValueNotInList(aResp->res, *bootType,
1436 "BootSourceOverrideMode");
1437 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001438 }
1439
1440 // Act on validated parameters
1441 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1442
1443 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001444 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001445 if (ec)
1446 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001447 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1448 if (ec.value() == boost::asio::error::host_unreachable)
1449 {
1450 messages::resourceNotFound(aResp->res, "Set", "BootType");
1451 return;
1452 }
1453 messages::internalError(aResp->res);
1454 return;
1455 }
1456 BMCWEB_LOG_DEBUG << "Boot type update done.";
1457 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001458 "xyz.openbmc_project.Settings",
1459 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001460 "org.freedesktop.DBus.Properties", "Set",
1461 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001462 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001463}
1464
1465/**
1466 * @brief Sets boot properties into DBUS object(s).
1467 *
1468 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001469 * @param[in] bootType The boot type to set.
1470 * @return Integer error code.
1471 */
1472inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1473 const std::optional<std::string>& bootEnable)
1474{
1475 if (!bootEnable)
1476 {
1477 return;
1478 }
1479 // Source target specified
1480 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1481
1482 bool bootOverrideEnable = false;
1483 bool bootOverridePersistent = false;
1484 // Figure out which DBUS interface and property to use
1485 if (*bootEnable == "Disabled")
1486 {
1487 bootOverrideEnable = false;
1488 }
1489 else if (*bootEnable == "Once")
1490 {
1491 bootOverrideEnable = true;
1492 bootOverridePersistent = false;
1493 }
1494 else if (*bootEnable == "Continuous")
1495 {
1496 bootOverrideEnable = true;
1497 bootOverridePersistent = true;
1498 }
1499 else
1500 {
George Liu0fda0f12021-11-16 10:06:17 +08001501 BMCWEB_LOG_DEBUG
1502 << "Invalid property value for BootSourceOverrideEnabled: "
1503 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001504 messages::propertyValueNotInList(aResp->res, *bootEnable,
1505 "BootSourceOverrideEnabled");
1506 return;
1507 }
1508
1509 // Act on validated parameters
1510 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1511
1512 crow::connections::systemBus->async_method_call(
1513 [aResp](const boost::system::error_code ec) {
1514 if (ec)
1515 {
1516 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1517 messages::internalError(aResp->res);
1518 return;
1519 }
1520 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1521 },
1522 "xyz.openbmc_project.Settings",
1523 "/xyz/openbmc_project/control/host0/boot",
1524 "org.freedesktop.DBus.Properties", "Set",
1525 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001526 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001527
1528 if (!bootOverrideEnable)
1529 {
1530 return;
1531 }
1532
1533 // In case boot override is enabled we need to set correct value for the
1534 // 'one_time' enable DBus interface
1535 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1536 << bootOverridePersistent;
1537
1538 crow::connections::systemBus->async_method_call(
1539 [aResp](const boost::system::error_code ec) {
1540 if (ec)
1541 {
1542 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1543 messages::internalError(aResp->res);
1544 return;
1545 }
1546 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1547 },
1548 "xyz.openbmc_project.Settings",
1549 "/xyz/openbmc_project/control/host0/boot/one_time",
1550 "org.freedesktop.DBus.Properties", "Set",
1551 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001552 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001553}
1554
1555/**
1556 * @brief Sets boot properties into DBUS object(s).
1557 *
1558 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301559 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301560 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001561 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301562 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001563inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001564 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301565{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001566 std::string bootSourceStr;
1567 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001568
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001569 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301570 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001571 return;
1572 }
1573
1574 // Source target specified
1575 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1576 // Figure out which DBUS interface and property to use
1577 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1578 {
1579 BMCWEB_LOG_DEBUG
1580 << "Invalid property value for BootSourceOverrideTarget: "
1581 << *bootSource;
1582 messages::propertyValueNotInList(aResp->res, *bootSource,
1583 "BootSourceTargetOverride");
1584 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001585 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301586
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001587 // Act on validated parameters
1588 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1589 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001590
1591 crow::connections::systemBus->async_method_call(
1592 [aResp](const boost::system::error_code ec) {
1593 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301594 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001595 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1596 messages::internalError(aResp->res);
1597 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301598 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001599 BMCWEB_LOG_DEBUG << "Boot source update done.";
1600 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001601 "xyz.openbmc_project.Settings",
1602 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001603 "org.freedesktop.DBus.Properties", "Set",
1604 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001605 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001606
1607 crow::connections::systemBus->async_method_call(
1608 [aResp](const boost::system::error_code ec) {
1609 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301610 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001611 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1612 messages::internalError(aResp->res);
1613 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301614 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001615 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1616 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001617 "xyz.openbmc_project.Settings",
1618 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001619 "org.freedesktop.DBus.Properties", "Set",
1620 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001621 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001622}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001623
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001624/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001625 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301626 *
1627 * @param[in] aResp Shared pointer for generating response message.
1628 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001629 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301630 * @param[in] bootEnable The boot override enable from incoming RF request.
1631 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001632 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301633 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001634
1635inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1636 const std::optional<std::string>& bootSource,
1637 const std::optional<std::string>& bootType,
1638 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301639{
1640 BMCWEB_LOG_DEBUG << "Set boot information.";
1641
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001642 setBootModeOrSource(aResp, bootSource);
1643 setBootType(aResp, bootType);
1644 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301645}
1646
George Liuc6a620f2020-04-10 17:18:11 +08001647/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001648 * @brief Sets AssetTag
1649 *
1650 * @param[in] aResp Shared pointer for generating response message.
1651 * @param[in] assetTag "AssetTag" from request.
1652 *
1653 * @return None.
1654 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001655inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001656 const std::string& assetTag)
1657{
1658 crow::connections::systemBus->async_method_call(
1659 [aResp, assetTag](
1660 const boost::system::error_code ec,
1661 const std::vector<std::pair<
1662 std::string,
1663 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1664 subtree) {
1665 if (ec)
1666 {
1667 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1668 messages::internalError(aResp->res);
1669 return;
1670 }
Ed Tanous26f69762022-01-25 09:49:11 -08001671 if (subtree.empty())
Gunnar Mills98e386e2020-10-30 14:58:09 -05001672 {
1673 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1674 messages::internalError(aResp->res);
1675 return;
1676 }
1677 // Assume only 1 system D-Bus object
1678 // Throw an error if there is more than 1
1679 if (subtree.size() > 1)
1680 {
1681 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1682 messages::internalError(aResp->res);
1683 return;
1684 }
1685 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1686 {
1687 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1688 messages::internalError(aResp->res);
1689 return;
1690 }
1691
1692 const std::string& path = subtree[0].first;
1693 const std::string& service = subtree[0].second.begin()->first;
1694
1695 if (service.empty())
1696 {
1697 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1698 messages::internalError(aResp->res);
1699 return;
1700 }
1701
1702 crow::connections::systemBus->async_method_call(
1703 [aResp](const boost::system::error_code ec2) {
1704 if (ec2)
1705 {
1706 BMCWEB_LOG_DEBUG
1707 << "D-Bus response error on AssetTag Set " << ec2;
1708 messages::internalError(aResp->res);
1709 return;
1710 }
1711 },
1712 service, path, "org.freedesktop.DBus.Properties", "Set",
1713 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001714 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001715 },
1716 "xyz.openbmc_project.ObjectMapper",
1717 "/xyz/openbmc_project/object_mapper",
1718 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1719 "/xyz/openbmc_project/inventory", int32_t(0),
1720 std::array<const char*, 1>{
1721 "xyz.openbmc_project.Inventory.Item.System"});
1722}
1723
1724/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001725 * @brief Sets automaticRetry (Auto Reboot)
1726 *
1727 * @param[in] aResp Shared pointer for generating response message.
1728 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1729 *
1730 * @return None.
1731 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001732inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001733 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001734{
1735 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1736
1737 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001738 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001739
1740 if (automaticRetryConfig == "Disabled")
1741 {
1742 autoRebootEnabled = false;
1743 }
1744 else if (automaticRetryConfig == "RetryAttempts")
1745 {
1746 autoRebootEnabled = true;
1747 }
1748 else
1749 {
George Liu0fda0f12021-11-16 10:06:17 +08001750 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001751 << automaticRetryConfig;
1752 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1753 "AutomaticRetryConfig");
1754 return;
1755 }
1756
1757 crow::connections::systemBus->async_method_call(
1758 [aResp](const boost::system::error_code ec) {
1759 if (ec)
1760 {
1761 messages::internalError(aResp->res);
1762 return;
1763 }
1764 },
1765 "xyz.openbmc_project.Settings",
1766 "/xyz/openbmc_project/control/host0/auto_reboot",
1767 "org.freedesktop.DBus.Properties", "Set",
1768 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001769 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001770}
1771
1772/**
George Liuc6a620f2020-04-10 17:18:11 +08001773 * @brief Sets power restore policy properties.
1774 *
1775 * @param[in] aResp Shared pointer for generating response message.
1776 * @param[in] policy power restore policy properties from request.
1777 *
1778 * @return None.
1779 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001780inline void
1781 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1782 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001783{
1784 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1785
1786 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001787 {"AlwaysOn",
1788 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1789 {"AlwaysOff",
1790 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1791 {"LastState",
1792 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001793
1794 std::string powerRestorPolicy;
1795
Gunnar Mills4e69c902021-01-05 19:50:11 -06001796 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001797 if (policyMapsIt == policyMaps.end())
1798 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001799 messages::propertyValueNotInList(aResp->res, policy,
1800 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001801 return;
1802 }
1803
1804 powerRestorPolicy = policyMapsIt->second;
1805
1806 crow::connections::systemBus->async_method_call(
1807 [aResp](const boost::system::error_code ec) {
1808 if (ec)
1809 {
1810 messages::internalError(aResp->res);
1811 return;
1812 }
1813 },
1814 "xyz.openbmc_project.Settings",
1815 "/xyz/openbmc_project/control/host0/power_restore_policy",
1816 "org.freedesktop.DBus.Properties", "Set",
1817 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001818 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001819}
1820
AppaRao Pulia6349912019-10-18 17:16:08 +05301821#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1822/**
1823 * @brief Retrieves provisioning status
1824 *
1825 * @param[in] aResp Shared pointer for completing asynchronous calls.
1826 *
1827 * @return None.
1828 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001829inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301830{
1831 BMCWEB_LOG_DEBUG << "Get OEM information.";
1832 crow::connections::systemBus->async_method_call(
1833 [aResp](const boost::system::error_code ec,
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001834 const std::vector<
1835 std::pair<std::string, dbus::utility::DbusVariantType>>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001836 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301837 nlohmann::json& oemPFR =
1838 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001839 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1840 "#OemComputerSystem.OpenBmc";
1841 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1842
AppaRao Pulia6349912019-10-18 17:16:08 +05301843 if (ec)
1844 {
1845 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301846 // not an error, don't have to have the interface
1847 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301848 return;
1849 }
1850
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001851 const bool* provState = nullptr;
1852 const bool* lockState = nullptr;
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001853 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1854 property : propertiesList)
AppaRao Pulia6349912019-10-18 17:16:08 +05301855 {
1856 if (property.first == "UfmProvisioned")
1857 {
1858 provState = std::get_if<bool>(&property.second);
1859 }
1860 else if (property.first == "UfmLocked")
1861 {
1862 lockState = std::get_if<bool>(&property.second);
1863 }
1864 }
1865
1866 if ((provState == nullptr) || (lockState == nullptr))
1867 {
1868 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1869 messages::internalError(aResp->res);
1870 return;
1871 }
1872
AppaRao Pulia6349912019-10-18 17:16:08 +05301873 if (*provState == true)
1874 {
1875 if (*lockState == true)
1876 {
1877 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1878 }
1879 else
1880 {
1881 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1882 }
1883 }
1884 else
1885 {
1886 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1887 }
1888 },
1889 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1890 "org.freedesktop.DBus.Properties", "GetAll",
1891 "xyz.openbmc_project.PFR.Attributes");
1892}
1893#endif
1894
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301895/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001896 * @brief Translate the PowerMode to a response message.
1897 *
1898 * @param[in] aResp Shared pointer for generating response message.
1899 * @param[in] modeValue PowerMode value to be translated
1900 *
1901 * @return None.
1902 */
1903inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1904 const std::string& modeValue)
1905{
1906 std::string modeString;
1907
George Liu0fda0f12021-11-16 10:06:17 +08001908 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001909 {
1910 aResp->res.jsonValue["PowerMode"] = "Static";
1911 }
George Liu0fda0f12021-11-16 10:06:17 +08001912 else if (
1913 modeValue ==
1914 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001915 {
1916 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1917 }
George Liu0fda0f12021-11-16 10:06:17 +08001918 else if (modeValue ==
1919 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001920 {
1921 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1922 }
George Liu0fda0f12021-11-16 10:06:17 +08001923 else if (modeValue ==
1924 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001925 {
1926 aResp->res.jsonValue["PowerMode"] = "OEM";
1927 }
1928 else
1929 {
1930 // Any other values would be invalid
1931 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1932 messages::internalError(aResp->res);
1933 }
1934}
1935
1936/**
1937 * @brief Retrieves system power mode
1938 *
1939 * @param[in] aResp Shared pointer for generating response message.
1940 *
1941 * @return None.
1942 */
1943inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1944{
1945 BMCWEB_LOG_DEBUG << "Get power mode.";
1946
1947 // Get Power Mode object path:
1948 crow::connections::systemBus->async_method_call(
1949 [aResp](
1950 const boost::system::error_code ec,
1951 const std::vector<std::pair<
1952 std::string,
1953 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1954 subtree) {
1955 if (ec)
1956 {
1957 BMCWEB_LOG_DEBUG
1958 << "DBUS response error on Power.Mode GetSubTree " << ec;
1959 // This is an optional D-Bus object so just return if
1960 // error occurs
1961 return;
1962 }
1963 if (subtree.empty())
1964 {
1965 // As noted above, this is an optional interface so just return
1966 // if there is no instance found
1967 return;
1968 }
1969 if (subtree.size() > 1)
1970 {
1971 // More then one PowerMode object is not supported and is an
1972 // error
1973 BMCWEB_LOG_DEBUG
1974 << "Found more than 1 system D-Bus Power.Mode objects: "
1975 << subtree.size();
1976 messages::internalError(aResp->res);
1977 return;
1978 }
1979 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1980 {
1981 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1982 messages::internalError(aResp->res);
1983 return;
1984 }
1985 const std::string& path = subtree[0].first;
1986 const std::string& service = subtree[0].second.begin()->first;
1987 if (service.empty())
1988 {
1989 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1990 messages::internalError(aResp->res);
1991 return;
1992 }
1993 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001994 sdbusplus::asio::getProperty<std::string>(
1995 *crow::connections::systemBus, service, path,
1996 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001997 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001998 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001999 if (ec)
2000 {
2001 BMCWEB_LOG_DEBUG
2002 << "DBUS response error on PowerMode Get: " << ec;
2003 messages::internalError(aResp->res);
2004 return;
2005 }
2006
Chris Cain3a2d04242021-05-28 16:57:10 -05002007 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2008 {"Static", "MaximumPerformance", "PowerSaving"};
2009
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002010 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2011 translatePowerMode(aResp, pmode);
2012 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002013 },
2014 "xyz.openbmc_project.ObjectMapper",
2015 "/xyz/openbmc_project/object_mapper",
2016 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2017 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2018}
2019
2020/**
2021 * @brief Validate the specified mode is valid and return the PowerMode
2022 * name associated with that string
2023 *
2024 * @param[in] aResp Shared pointer for generating response message.
2025 * @param[in] modeString String representing the desired PowerMode
2026 *
2027 * @return PowerMode value or empty string if mode is not valid
2028 */
2029inline std::string
2030 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2031 const std::string& modeString)
2032{
2033 std::string mode;
2034
2035 if (modeString == "Static")
2036 {
2037 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2038 }
2039 else if (modeString == "MaximumPerformance")
2040 {
George Liu0fda0f12021-11-16 10:06:17 +08002041 mode =
2042 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002043 }
2044 else if (modeString == "PowerSaving")
2045 {
2046 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2047 }
2048 else
2049 {
2050 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2051 }
2052 return mode;
2053}
2054
2055/**
2056 * @brief Sets system power mode.
2057 *
2058 * @param[in] aResp Shared pointer for generating response message.
2059 * @param[in] pmode System power mode from request.
2060 *
2061 * @return None.
2062 */
2063inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2064 const std::string& pmode)
2065{
2066 BMCWEB_LOG_DEBUG << "Set power mode.";
2067
2068 std::string powerMode = validatePowerMode(aResp, pmode);
2069 if (powerMode.empty())
2070 {
2071 return;
2072 }
2073
2074 // Get Power Mode object path:
2075 crow::connections::systemBus->async_method_call(
2076 [aResp, powerMode](
2077 const boost::system::error_code ec,
2078 const std::vector<std::pair<
2079 std::string,
2080 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2081 subtree) {
2082 if (ec)
2083 {
2084 BMCWEB_LOG_DEBUG
2085 << "DBUS response error on Power.Mode GetSubTree " << ec;
2086 // This is an optional D-Bus object, but user attempted to patch
2087 messages::internalError(aResp->res);
2088 return;
2089 }
2090 if (subtree.empty())
2091 {
2092 // This is an optional D-Bus object, but user attempted to patch
2093 messages::resourceNotFound(aResp->res, "ComputerSystem",
2094 "PowerMode");
2095 return;
2096 }
2097 if (subtree.size() > 1)
2098 {
2099 // More then one PowerMode object is not supported and is an
2100 // error
2101 BMCWEB_LOG_DEBUG
2102 << "Found more than 1 system D-Bus Power.Mode objects: "
2103 << subtree.size();
2104 messages::internalError(aResp->res);
2105 return;
2106 }
2107 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2108 {
2109 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2110 messages::internalError(aResp->res);
2111 return;
2112 }
2113 const std::string& path = subtree[0].first;
2114 const std::string& service = subtree[0].second.begin()->first;
2115 if (service.empty())
2116 {
2117 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2118 messages::internalError(aResp->res);
2119 return;
2120 }
2121
2122 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2123 << path;
2124
2125 // Set the Power Mode property
2126 crow::connections::systemBus->async_method_call(
2127 [aResp](const boost::system::error_code ec) {
2128 if (ec)
2129 {
2130 messages::internalError(aResp->res);
2131 return;
2132 }
2133 },
2134 service, path, "org.freedesktop.DBus.Properties", "Set",
2135 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002136 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002137 },
2138 "xyz.openbmc_project.ObjectMapper",
2139 "/xyz/openbmc_project/object_mapper",
2140 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2141 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2142}
2143
2144/**
Yong Li51709ff2019-09-30 14:13:04 +08002145 * @brief Translates watchdog timeout action DBUS property value to redfish.
2146 *
2147 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2148 *
2149 * @return Returns as a string, the timeout action in Redfish terms. If
2150 * translation cannot be done, returns an empty string.
2151 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002152inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002153{
2154 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2155 {
2156 return "None";
2157 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002158 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002159 {
2160 return "ResetSystem";
2161 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002162 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002163 {
2164 return "PowerDown";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002167 {
2168 return "PowerCycle";
2169 }
2170
2171 return "";
2172}
2173
2174/**
Yong Lic45f0082019-10-10 14:19:01 +08002175 *@brief Translates timeout action from Redfish to DBUS property value.
2176 *
2177 *@param[in] rfAction The timeout action in Redfish.
2178 *
2179 *@return Returns as a string, the time_out action as expected by DBUS.
2180 *If translation cannot be done, returns an empty string.
2181 */
2182
Ed Tanous23a21a12020-07-25 04:45:05 +00002183inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002184{
2185 if (rfAction == "None")
2186 {
2187 return "xyz.openbmc_project.State.Watchdog.Action.None";
2188 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002189 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002190 {
2191 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2192 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002193 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002194 {
2195 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2196 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002197 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002198 {
2199 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2200 }
2201
2202 return "";
2203}
2204
2205/**
Yong Li51709ff2019-09-30 14:13:04 +08002206 * @brief Retrieves host watchdog timer properties over DBUS
2207 *
2208 * @param[in] aResp Shared pointer for completing asynchronous calls.
2209 *
2210 * @return None.
2211 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002212inline void
2213 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002214{
2215 BMCWEB_LOG_DEBUG << "Get host watchodg";
2216 crow::connections::systemBus->async_method_call(
2217 [aResp](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002218 const PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002219 if (ec)
2220 {
2221 // watchdog service is stopped
2222 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2223 return;
2224 }
2225
2226 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2227
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002228 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002229 aResp->res.jsonValue["HostWatchdogTimer"];
2230
2231 // watchdog service is running/enabled
2232 hostWatchdogTimer["Status"]["State"] = "Enabled";
2233
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002234 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002235 {
2236 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2237 if (property.first == "Enabled")
2238 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002239 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002240
2241 if (!state)
2242 {
2243 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002244 return;
Yong Li51709ff2019-09-30 14:13:04 +08002245 }
2246
2247 hostWatchdogTimer["FunctionEnabled"] = *state;
2248 }
2249 else if (property.first == "ExpireAction")
2250 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002251 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002252 std::get_if<std::string>(&property.second);
2253 if (!s)
2254 {
2255 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002256 return;
Yong Li51709ff2019-09-30 14:13:04 +08002257 }
2258
2259 std::string action = dbusToRfWatchdogAction(*s);
2260 if (action.empty())
2261 {
2262 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002263 return;
Yong Li51709ff2019-09-30 14:13:04 +08002264 }
2265 hostWatchdogTimer["TimeoutAction"] = action;
2266 }
2267 }
2268 },
2269 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2270 "org.freedesktop.DBus.Properties", "GetAll",
2271 "xyz.openbmc_project.State.Watchdog");
2272}
2273
2274/**
Yong Lic45f0082019-10-10 14:19:01 +08002275 * @brief Sets Host WatchDog Timer properties.
2276 *
2277 * @param[in] aResp Shared pointer for generating response message.
2278 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2279 * RF request.
2280 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2281 *
2282 * @return None.
2283 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002284inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002285 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002286 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002287{
2288 BMCWEB_LOG_DEBUG << "Set host watchdog";
2289
2290 if (wdtTimeOutAction)
2291 {
2292 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2293 // check if TimeOut Action is Valid
2294 if (wdtTimeOutActStr.empty())
2295 {
2296 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2297 << *wdtTimeOutAction;
2298 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2299 "TimeoutAction");
2300 return;
2301 }
2302
2303 crow::connections::systemBus->async_method_call(
2304 [aResp](const boost::system::error_code ec) {
2305 if (ec)
2306 {
2307 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2308 messages::internalError(aResp->res);
2309 return;
2310 }
2311 },
2312 "xyz.openbmc_project.Watchdog",
2313 "/xyz/openbmc_project/watchdog/host0",
2314 "org.freedesktop.DBus.Properties", "Set",
2315 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002316 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002317 }
2318
2319 if (wdtEnable)
2320 {
2321 crow::connections::systemBus->async_method_call(
2322 [aResp](const boost::system::error_code ec) {
2323 if (ec)
2324 {
2325 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2326 messages::internalError(aResp->res);
2327 return;
2328 }
2329 },
2330 "xyz.openbmc_project.Watchdog",
2331 "/xyz/openbmc_project/watchdog/host0",
2332 "org.freedesktop.DBus.Properties", "Set",
2333 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002334 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002335 }
2336}
2337
Chris Cain37bbf982021-09-20 10:53:09 -05002338using ipsPropertiesType =
2339 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2340/**
2341 * @brief Parse the Idle Power Saver properties into json
2342 *
2343 * @param[in] aResp Shared pointer for completing asynchronous calls.
2344 * @param[in] properties IPS property data from DBus.
2345 *
2346 * @return true if successful
2347 */
Ed Tanousf6674222021-11-13 09:41:41 -08002348inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2349 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002350{
2351 for (const auto& property : properties)
2352 {
2353 if (property.first == "Enabled")
2354 {
2355 const bool* state = std::get_if<bool>(&property.second);
2356 if (!state)
2357 {
2358 return false;
2359 }
2360 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2361 }
2362 else if (property.first == "EnterUtilizationPercent")
2363 {
2364 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2365 if (!util)
2366 {
2367 return false;
2368 }
2369 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2370 }
2371 else if (property.first == "EnterDwellTime")
2372 {
2373 // Convert Dbus time from milliseconds to seconds
2374 const uint64_t* timeMilliseconds =
2375 std::get_if<uint64_t>(&property.second);
2376 if (!timeMilliseconds)
2377 {
2378 return false;
2379 }
2380 const std::chrono::duration<uint64_t, std::milli> ms(
2381 *timeMilliseconds);
2382 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2383 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2384 .count();
2385 }
2386 else if (property.first == "ExitUtilizationPercent")
2387 {
2388 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2389 if (!util)
2390 {
2391 return false;
2392 }
2393 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2394 }
2395 else if (property.first == "ExitDwellTime")
2396 {
2397 // Convert Dbus time from milliseconds to seconds
2398 const uint64_t* timeMilliseconds =
2399 std::get_if<uint64_t>(&property.second);
2400 if (!timeMilliseconds)
2401 {
2402 return false;
2403 }
2404 const std::chrono::duration<uint64_t, std::milli> ms(
2405 *timeMilliseconds);
2406 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2407 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2408 .count();
2409 }
2410 else
2411 {
2412 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2413 << property.first;
2414 }
2415 }
2416
2417 return true;
2418}
2419
2420/**
2421 * @brief Retrieves host watchdog timer properties over DBUS
2422 *
2423 * @param[in] aResp Shared pointer for completing asynchronous calls.
2424 *
2425 * @return None.
2426 */
2427inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2428{
2429 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2430
2431 // Get IdlePowerSaver object path:
2432 crow::connections::systemBus->async_method_call(
2433 [aResp](
2434 const boost::system::error_code ec,
2435 const std::vector<std::pair<
2436 std::string,
2437 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2438 subtree) {
2439 if (ec)
2440 {
2441 BMCWEB_LOG_DEBUG
2442 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2443 << ec;
2444 messages::internalError(aResp->res);
2445 return;
2446 }
2447 if (subtree.empty())
2448 {
2449 // This is an optional interface so just return
2450 // if there is no instance found
2451 BMCWEB_LOG_DEBUG << "No instances found";
2452 return;
2453 }
2454 if (subtree.size() > 1)
2455 {
2456 // More then one PowerIdlePowerSaver object is not supported and
2457 // is an error
2458 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2459 "Power.IdlePowerSaver objects: "
2460 << subtree.size();
2461 messages::internalError(aResp->res);
2462 return;
2463 }
2464 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2465 {
2466 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2467 messages::internalError(aResp->res);
2468 return;
2469 }
2470 const std::string& path = subtree[0].first;
2471 const std::string& service = subtree[0].second.begin()->first;
2472 if (service.empty())
2473 {
2474 BMCWEB_LOG_DEBUG
2475 << "Power.IdlePowerSaver service mapper error!";
2476 messages::internalError(aResp->res);
2477 return;
2478 }
2479
2480 // Valid IdlePowerSaver object found, now read the current values
2481 crow::connections::systemBus->async_method_call(
2482 [aResp](const boost::system::error_code ec,
2483 ipsPropertiesType& properties) {
2484 if (ec)
2485 {
2486 BMCWEB_LOG_ERROR
2487 << "DBUS response error on IdlePowerSaver GetAll: "
2488 << ec;
2489 messages::internalError(aResp->res);
2490 return;
2491 }
2492
Ed Tanouse05aec52022-01-25 10:28:56 -08002493 if (!parseIpsProperties(aResp, properties))
Chris Cain37bbf982021-09-20 10:53:09 -05002494 {
2495 messages::internalError(aResp->res);
2496 return;
2497 }
2498 },
2499 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2500 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2501 },
2502 "xyz.openbmc_project.ObjectMapper",
2503 "/xyz/openbmc_project/object_mapper",
2504 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2505 std::array<const char*, 1>{
2506 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2507
2508 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2509}
2510
2511/**
2512 * @brief Sets Idle Power Saver properties.
2513 *
2514 * @param[in] aResp Shared pointer for generating response message.
2515 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2516 * RF request.
2517 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2518 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2519 * before entering idle state.
2520 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2521 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2522 * before exiting idle state
2523 *
2524 * @return None.
2525 */
2526inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2527 const std::optional<bool> ipsEnable,
2528 const std::optional<uint8_t> ipsEnterUtil,
2529 const std::optional<uint64_t> ipsEnterTime,
2530 const std::optional<uint8_t> ipsExitUtil,
2531 const std::optional<uint64_t> ipsExitTime)
2532{
2533 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2534
2535 // Get IdlePowerSaver object path:
2536 crow::connections::systemBus->async_method_call(
2537 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2538 ipsExitTime](
2539 const boost::system::error_code ec,
2540 const std::vector<std::pair<
2541 std::string,
2542 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2543 subtree) {
2544 if (ec)
2545 {
2546 BMCWEB_LOG_DEBUG
2547 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2548 << ec;
2549 messages::internalError(aResp->res);
2550 return;
2551 }
2552 if (subtree.empty())
2553 {
2554 // This is an optional D-Bus object, but user attempted to patch
2555 messages::resourceNotFound(aResp->res, "ComputerSystem",
2556 "IdlePowerSaver");
2557 return;
2558 }
2559 if (subtree.size() > 1)
2560 {
2561 // More then one PowerIdlePowerSaver object is not supported and
2562 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002563 BMCWEB_LOG_DEBUG
2564 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2565 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002566 messages::internalError(aResp->res);
2567 return;
2568 }
2569 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2570 {
2571 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2572 messages::internalError(aResp->res);
2573 return;
2574 }
2575 const std::string& path = subtree[0].first;
2576 const std::string& service = subtree[0].second.begin()->first;
2577 if (service.empty())
2578 {
2579 BMCWEB_LOG_DEBUG
2580 << "Power.IdlePowerSaver service mapper error!";
2581 messages::internalError(aResp->res);
2582 return;
2583 }
2584
2585 // Valid Power IdlePowerSaver object found, now set any values that
2586 // need to be updated
2587
2588 if (ipsEnable)
2589 {
2590 crow::connections::systemBus->async_method_call(
2591 [aResp](const boost::system::error_code ec) {
2592 if (ec)
2593 {
2594 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2595 messages::internalError(aResp->res);
2596 return;
2597 }
2598 },
2599 service, path, "org.freedesktop.DBus.Properties", "Set",
2600 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002601 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002602 }
2603 if (ipsEnterUtil)
2604 {
2605 crow::connections::systemBus->async_method_call(
2606 [aResp](const boost::system::error_code ec) {
2607 if (ec)
2608 {
2609 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2610 messages::internalError(aResp->res);
2611 return;
2612 }
2613 },
2614 service, path, "org.freedesktop.DBus.Properties", "Set",
2615 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2616 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002617 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002618 }
2619 if (ipsEnterTime)
2620 {
2621 // Convert from seconds into milliseconds for DBus
2622 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2623 crow::connections::systemBus->async_method_call(
2624 [aResp](const boost::system::error_code ec) {
2625 if (ec)
2626 {
2627 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2628 messages::internalError(aResp->res);
2629 return;
2630 }
2631 },
2632 service, path, "org.freedesktop.DBus.Properties", "Set",
2633 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002634 "EnterDwellTime",
2635 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002636 }
2637 if (ipsExitUtil)
2638 {
2639 crow::connections::systemBus->async_method_call(
2640 [aResp](const boost::system::error_code ec) {
2641 if (ec)
2642 {
2643 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2644 messages::internalError(aResp->res);
2645 return;
2646 }
2647 },
2648 service, path, "org.freedesktop.DBus.Properties", "Set",
2649 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2650 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002651 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002652 }
2653 if (ipsExitTime)
2654 {
2655 // Convert from seconds into milliseconds for DBus
2656 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2657 crow::connections::systemBus->async_method_call(
2658 [aResp](const boost::system::error_code ec) {
2659 if (ec)
2660 {
2661 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2662 messages::internalError(aResp->res);
2663 return;
2664 }
2665 },
2666 service, path, "org.freedesktop.DBus.Properties", "Set",
2667 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002668 "ExitDwellTime",
2669 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002670 }
2671 },
2672 "xyz.openbmc_project.ObjectMapper",
2673 "/xyz/openbmc_project/object_mapper",
2674 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2675 std::array<const char*, 1>{
2676 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2677
2678 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2679}
2680
Yong Lic45f0082019-10-10 14:19:01 +08002681/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002682 * SystemsCollection derived class for delivering ComputerSystems Collection
2683 * Schema
2684 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002685inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002686{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002687 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002688 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002689 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002690 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002691 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2692 asyncResp->res.jsonValue["@odata.type"] =
2693 "#ComputerSystemCollection.ComputerSystemCollection";
2694 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2695 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002696
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002697 sdbusplus::asio::getProperty<std::string>(
2698 *crow::connections::systemBus,
2699 "xyz.openbmc_project.Settings",
2700 "/xyz/openbmc_project/network/hypervisor",
2701 "xyz.openbmc_project.Network.SystemConfiguration",
2702 "HostName",
2703 [asyncResp](const boost::system::error_code ec,
2704 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002705 nlohmann::json& ifaceArray =
2706 asyncResp->res.jsonValue["Members"];
2707 ifaceArray = nlohmann::json::array();
2708 auto& count =
2709 asyncResp->res.jsonValue["Members@odata.count"];
2710 ifaceArray.push_back(
2711 {{"@odata.id", "/redfish/v1/Systems/system"}});
2712 count = ifaceArray.size();
2713 if (!ec)
2714 {
2715 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2716 ifaceArray.push_back(
2717 {{"@odata.id",
2718 "/redfish/v1/Systems/hypervisor"}});
2719 count = ifaceArray.size();
2720 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002721 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002722 });
2723}
Sunitha Harish462023a2020-02-19 08:34:59 -06002724
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002725/**
2726 * Function transceives data with dbus directly.
2727 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002728inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002729{
2730 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2731 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2732 constexpr char const* interfaceName =
2733 "xyz.openbmc_project.Control.Host.NMI";
2734 constexpr char const* method = "NMI";
2735
2736 crow::connections::systemBus->async_method_call(
2737 [asyncResp](const boost::system::error_code ec) {
2738 if (ec)
2739 {
2740 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2741 messages::internalError(asyncResp->res);
2742 return;
2743 }
2744 messages::success(asyncResp->res);
2745 },
2746 serviceName, objectPath, interfaceName, method);
2747}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002748
2749/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002750 * SystemActionsReset class supports handle POST method for Reset action.
2751 * The class retrieves and sends data directly to D-Bus.
2752 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002753inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002754{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002755 /**
2756 * Function handles POST method request.
2757 * Analyzes POST body message before sends Reset request data to D-Bus.
2758 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002759 BMCWEB_ROUTE(app,
2760 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002761 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002762 .methods(
2763 boost::beast::http::verb::
2764 post)([](const crow::Request& req,
2765 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2766 std::string resetType;
2767 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2768 resetType))
2769 {
2770 return;
2771 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002772
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002773 // Get the command and host vs. chassis
2774 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002775 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002776 if ((resetType == "On") || (resetType == "ForceOn"))
2777 {
2778 command = "xyz.openbmc_project.State.Host.Transition.On";
2779 hostCommand = true;
2780 }
2781 else if (resetType == "ForceOff")
2782 {
2783 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2784 hostCommand = false;
2785 }
2786 else if (resetType == "ForceRestart")
2787 {
2788 command =
2789 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2790 hostCommand = true;
2791 }
2792 else if (resetType == "GracefulShutdown")
2793 {
2794 command = "xyz.openbmc_project.State.Host.Transition.Off";
2795 hostCommand = true;
2796 }
2797 else if (resetType == "GracefulRestart")
2798 {
George Liu0fda0f12021-11-16 10:06:17 +08002799 command =
2800 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002801 hostCommand = true;
2802 }
2803 else if (resetType == "PowerCycle")
2804 {
2805 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2806 hostCommand = true;
2807 }
2808 else if (resetType == "Nmi")
2809 {
2810 doNMI(asyncResp);
2811 return;
2812 }
2813 else
2814 {
2815 messages::actionParameterUnknown(asyncResp->res, "Reset",
2816 resetType);
2817 return;
2818 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002819
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002820 if (hostCommand)
2821 {
2822 crow::connections::systemBus->async_method_call(
2823 [asyncResp, resetType](const boost::system::error_code ec) {
2824 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002825 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002826 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2827 if (ec.value() ==
2828 boost::asio::error::invalid_argument)
2829 {
2830 messages::actionParameterNotSupported(
2831 asyncResp->res, resetType, "Reset");
2832 }
2833 else
2834 {
2835 messages::internalError(asyncResp->res);
2836 }
2837 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002838 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839 messages::success(asyncResp->res);
2840 },
2841 "xyz.openbmc_project.State.Host",
2842 "/xyz/openbmc_project/state/host0",
2843 "org.freedesktop.DBus.Properties", "Set",
2844 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002845 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002846 }
2847 else
2848 {
2849 crow::connections::systemBus->async_method_call(
2850 [asyncResp, resetType](const boost::system::error_code ec) {
2851 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002852 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002853 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2854 if (ec.value() ==
2855 boost::asio::error::invalid_argument)
2856 {
2857 messages::actionParameterNotSupported(
2858 asyncResp->res, resetType, "Reset");
2859 }
2860 else
2861 {
2862 messages::internalError(asyncResp->res);
2863 }
2864 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002865 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002866 messages::success(asyncResp->res);
2867 },
2868 "xyz.openbmc_project.State.Chassis",
2869 "/xyz/openbmc_project/state/chassis0",
2870 "org.freedesktop.DBus.Properties", "Set",
2871 "xyz.openbmc_project.State.Chassis",
2872 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002873 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874 }
2875 });
2876}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002877
2878/**
Ed Tanous66173382018-08-15 18:20:59 -07002879 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002880 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002881inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002882{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002883
Ed Tanous1abe55e2018-09-05 08:30:59 -07002884 /**
2885 * Functions triggers appropriate requests on DBus
2886 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002887 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002888 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002889 .methods(
2890 boost::beast::http::verb::
2891 get)([](const crow::Request&,
2892 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2893 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002894 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002895 asyncResp->res.jsonValue["Name"] = "system";
2896 asyncResp->res.jsonValue["Id"] = "system";
2897 asyncResp->res.jsonValue["SystemType"] = "Physical";
2898 asyncResp->res.jsonValue["Description"] = "Computer System";
2899 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2900 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2901 "Disabled";
2902 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2903 uint64_t(0);
2904 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2905 "Disabled";
2906 asyncResp->res.jsonValue["@odata.id"] =
2907 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002908
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002909 asyncResp->res.jsonValue["Processors"] = {
2910 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2911 asyncResp->res.jsonValue["Memory"] = {
2912 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2913 asyncResp->res.jsonValue["Storage"] = {
2914 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002915
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002916 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2917 {"target",
2918 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2919 {"@Redfish.ActionInfo",
2920 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002921
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002922 asyncResp->res.jsonValue["LogServices"] = {
2923 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002924
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002925 asyncResp->res.jsonValue["Bios"] = {
2926 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002927
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002928 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2929 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002930
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002931 asyncResp->res.jsonValue["Status"] = {
2932 {"Health", "OK"},
2933 {"State", "Enabled"},
2934 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002935
2936 // Fill in SerialConsole info
2937 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2938 15;
2939 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2940 {"ServiceEnabled", true},
2941 };
2942 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2943 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2944 {"ServiceEnabled", true},
2945 {"Port", 2200},
2946 // https://github.com/openbmc/docs/blob/master/console.md
2947 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2948 };
2949
2950#ifdef BMCWEB_ENABLE_KVM
2951 // Fill in GraphicalConsole info
2952 asyncResp->res.jsonValue["GraphicalConsole"] = {
2953 {"ServiceEnabled", true},
2954 {"MaxConcurrentSessions", 4},
2955 {"ConnectTypesSupported", {"KVMIP"}},
2956 };
2957#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002958 constexpr const std::array<const char*, 4> inventoryForSystems = {
2959 "xyz.openbmc_project.Inventory.Item.Dimm",
2960 "xyz.openbmc_project.Inventory.Item.Cpu",
2961 "xyz.openbmc_project.Inventory.Item.Drive",
2962 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002963
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002964 auto health = std::make_shared<HealthPopulate>(asyncResp);
2965 crow::connections::systemBus->async_method_call(
2966 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002967 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002968 if (ec)
2969 {
2970 // no inventory
2971 return;
2972 }
2973
Ed Tanous914e2d52022-01-07 11:38:34 -08002974 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002975 },
2976 "xyz.openbmc_project.ObjectMapper",
2977 "/xyz/openbmc_project/object_mapper",
2978 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2979 int32_t(0), inventoryForSystems);
2980
2981 health->populate();
2982
2983 getMainChassisId(
2984 asyncResp, [](const std::string& chassisId,
2985 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2986 aRsp->res.jsonValue["Links"]["Chassis"] = {
2987 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2988 });
2989
2990 getLocationIndicatorActive(asyncResp);
2991 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2992 getIndicatorLedState(asyncResp);
2993 getComputerSystem(asyncResp, health);
2994 getHostState(asyncResp);
2995 getBootProperties(asyncResp);
2996 getBootProgress(asyncResp);
2997 getPCIeDeviceList(asyncResp, "PCIeDevices");
2998 getHostWatchdogTimer(asyncResp);
2999 getPowerRestorePolicy(asyncResp);
3000 getAutomaticRetry(asyncResp);
3001 getLastResetTime(asyncResp);
3002#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
3003 getProvisioningStatus(asyncResp);
3004#endif
Ali Ahmed19817712021-06-29 17:01:52 -05003005 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05003006 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003007 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003008 });
3009 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003010 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003011 .methods(boost::beast::http::verb::patch)(
3012 [](const crow::Request& req,
3013 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3014 std::optional<bool> locationIndicatorActive;
3015 std::optional<std::string> indicatorLed;
3016 std::optional<nlohmann::json> bootProps;
3017 std::optional<nlohmann::json> wdtTimerProps;
3018 std::optional<std::string> assetTag;
3019 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003020 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003021 std::optional<nlohmann::json> ipsProps;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003022 if (!json_util::readJson(
3023 req, asyncResp->res, "IndicatorLED", indicatorLed,
3024 "LocationIndicatorActive", locationIndicatorActive,
3025 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3026 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003027 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3028 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003029 {
James Feistb49ac872019-05-21 15:12:01 -07003030 return;
3031 }
3032
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003033 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003034
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003035 if (assetTag)
3036 {
3037 setAssetTag(asyncResp, *assetTag);
3038 }
James Feistb49ac872019-05-21 15:12:01 -07003039
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003040 if (wdtTimerProps)
3041 {
3042 std::optional<bool> wdtEnable;
3043 std::optional<std::string> wdtTimeOutAction;
3044
3045 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3046 "FunctionEnabled", wdtEnable,
3047 "TimeoutAction", wdtTimeOutAction))
3048 {
3049 return;
3050 }
3051 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3052 }
3053
3054 if (bootProps)
3055 {
3056 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003057 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003058 std::optional<std::string> bootEnable;
3059 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003060 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003061
3062 if (!json_util::readJson(
3063 *bootProps, asyncResp->res,
3064 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003065 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003066 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003067 "AutomaticRetryConfig", automaticRetryConfig,
3068 "TrustedModuleRequiredToBoot",
3069 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003070 {
3071 return;
3072 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003073
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003074 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003075 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003076 setBootProperties(asyncResp, bootSource, bootType,
3077 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003078 }
3079 if (automaticRetryConfig)
3080 {
3081 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3082 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003083
3084 if (trustedModuleRequiredToBoot)
3085 {
3086 setTrustedModuleRequiredToBoot(
3087 asyncResp, *trustedModuleRequiredToBoot);
3088 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003089 }
3090
3091 if (locationIndicatorActive)
3092 {
3093 setLocationIndicatorActive(asyncResp,
3094 *locationIndicatorActive);
3095 }
3096
3097 // TODO (Gunnar): Remove IndicatorLED after enough time has
3098 // passed
3099 if (indicatorLed)
3100 {
3101 setIndicatorLedState(asyncResp, *indicatorLed);
3102 asyncResp->res.addHeader(
3103 boost::beast::http::field::warning,
3104 "299 - \"IndicatorLED is deprecated. Use "
3105 "LocationIndicatorActive instead.\"");
3106 }
3107
3108 if (powerRestorePolicy)
3109 {
3110 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3111 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003112
3113 if (powerMode)
3114 {
3115 setPowerMode(asyncResp, *powerMode);
3116 }
Chris Cain37bbf982021-09-20 10:53:09 -05003117
3118 if (ipsProps)
3119 {
3120 std::optional<bool> ipsEnable;
3121 std::optional<uint8_t> ipsEnterUtil;
3122 std::optional<uint64_t> ipsEnterTime;
3123 std::optional<uint8_t> ipsExitUtil;
3124 std::optional<uint64_t> ipsExitTime;
3125
3126 if (!json_util::readJson(
3127 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3128 "EnterUtilizationPercent", ipsEnterUtil,
3129 "EnterDwellTimeSeconds", ipsEnterTime,
3130 "ExitUtilizationPercent", ipsExitUtil,
3131 "ExitDwellTimeSeconds", ipsExitTime))
3132 {
3133 return;
3134 }
3135 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3136 ipsEnterTime, ipsExitUtil, ipsExitTime);
3137 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003138 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003139}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303140
3141/**
3142 * SystemResetActionInfo derived class for delivering Computer Systems
3143 * ResetType AllowableValues using ResetInfo schema.
3144 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003145inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303146{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303147
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303148 /**
3149 * Functions triggers appropriate requests on DBus
3150 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003151 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003152 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003153 .methods(boost::beast::http::verb::get)(
3154 [](const crow::Request&,
3155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3156 asyncResp->res.jsonValue = {
3157 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3158 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3159 {"Name", "Reset Action Info"},
3160 {"Id", "ResetActionInfo"},
3161 {"Parameters",
3162 {{{"Name", "ResetType"},
3163 {"Required", true},
3164 {"DataType", "String"},
3165 {"AllowableValues",
3166 {"On", "ForceOff", "ForceOn", "ForceRestart",
3167 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3168 "Nmi"}}}}}};
3169 });
3170}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003171} // namespace redfish