blob: a21b6a0f4a0577f911857c065ea0817c6fb26c33 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
23
John Edward Broadbent7e860f12021-04-08 15:57:16 -070024#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070025#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080026#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070027#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070028#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060029#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050031
Ed Tanousabf2add2019-01-22 16:40:12 -080032#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034namespace redfish
35{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020036
Alpana Kumari9d3ae102019-04-12 06:49:32 -050037/**
38 * @brief Updates the Functional State of DIMMs
39 *
40 * @param[in] aResp Shared pointer for completing asynchronous calls
41 * @param[in] dimmState Dimm's Functional state, true/false
42 *
43 * @return None.
44 */
zhanghch058d1b46d2021-04-01 11:18:24 +080045inline void
46 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070047 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070049 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050
Gunnar Mills4e0453b2020-07-08 14:00:30 -050051 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052 // Update STATE only if previous State was DISABLED and current Dimm is
53 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050054 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
56 if (prevMemSummary == "Disabled")
57 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070058 if (isDimmFunctional == true)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 {
60 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
61 "Enabled";
62 }
63 }
64}
65
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050066/*
67 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
68 *
69 * @param[in] aResp Shared pointer for completing asynchronous calls
70 * @param[in] cpuPresenceState CPU present or not
71 *
72 * @return None.
73 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074inline void
75 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
76 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070078 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079
Jonathan Doman1e1e5982021-06-11 09:36:17 -070080 if (isCpuPresent == true)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050082 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080083 aResp->res.jsonValue["ProcessorSummary"]["Count"];
84 auto procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050085 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080086 if (procCountPtr != nullptr)
87 {
88 // shouldn't be possible to be nullptr
89 *procCountPtr += 1;
90 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092}
93
94/*
95 * @brief Update "ProcessorSummary" "Status" "State" based on
96 * CPU Functional State
97 *
98 * @param[in] aResp Shared pointer for completing asynchronous calls
99 * @param[in] cpuFunctionalState is CPU functional true/false
100 *
101 * @return None.
102 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700103inline void
104 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
105 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700107 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
111
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500112 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113 // Update STATE only if previous State was Non_Functional and current CPU is
114 // Functional.
115 if (prevProcState == "Disabled")
116 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700117 if (isCpuFunctional == true)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 {
119 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
120 "Enabled";
121 }
122 }
123}
124
Ali Ahmed03fbed92021-09-03 02:33:43 -0500125inline void getProcessorProperties(
126 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
127 const std::string& path,
Ed Tanous168e20c2021-12-13 14:39:53 -0800128 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
Ali Ahmed03fbed92021-09-03 02:33:43 -0500129 properties)
130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
179 if (!coreCountVal)
180 {
181 messages::internalError(aResp->res);
182 return;
183 }
184
185 nlohmann::json& coreCount =
186 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
187 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
188
189 if (coreCountPtr == nullptr)
190 {
191 coreCount = 0;
192 }
193 else
194 {
195 *coreCountPtr += *coreCountVal;
196 }
197 }
198 }
199}
200
201/*
202 * @brief Get ProcessorSummary fields
203 *
204 * @param[in] aResp Shared pointer for completing asynchronous calls
205 * @param[in] service dbus service for Cpu Information
206 * @param[in] path dbus path for Cpu
207 *
208 * @return None.
209 */
210inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 const std::string& service,
212 const std::string& path)
213{
214
215 crow::connections::systemBus->async_method_call(
216 [aResp, service,
217 path](const boost::system::error_code ec2,
218 const std::vector<std::pair<
Ed Tanous168e20c2021-12-13 14:39:53 -0800219 std::string, dbus::utility::DbusVariantType>>& properties) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500220 if (ec2)
221 {
222 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
223 messages::internalError(aResp->res);
224 return;
225 }
226 getProcessorProperties(aResp, service, path, properties);
227 },
228 service, path, "org.freedesktop.DBus.Properties", "GetAll",
229 "xyz.openbmc_project.Inventory.Item.Cpu");
230}
231
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500232/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700233 * @brief Retrieves computer system properties over dbus
234 *
235 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500236 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700237 *
238 * @return None.
239 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700240inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800241 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700242 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700243{
Ed Tanous6c34de42018-08-29 13:37:36 -0700244 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500245
Ed Tanous6c34de42018-08-29 13:37:36 -0700246 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700247 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700248 const boost::system::error_code ec,
249 const std::vector<std::pair<
250 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500251 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
252 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700253 if (ec)
254 {
255 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700256 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700257 return;
258 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700259 // Iterate over all retrieved ObjectPaths.
260 for (const std::pair<std::string,
261 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500262 std::string, std::vector<std::string>>>>&
263 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700264 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500265 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 BMCWEB_LOG_DEBUG << "Got path: " << path;
267 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500268 std::pair<std::string, std::vector<std::string>>>&
269 connectionNames = object.second;
Ed Tanous6c34de42018-08-29 13:37:36 -0700270 if (connectionNames.size() < 1)
271 {
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
314 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800315 {
Ed Tanous168e20c2021-12-13 14:39:53 -0800316 for (const std::pair<
317 std::string,
318 dbus::utility::
319 DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700321 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800322 if (property.first !=
323 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700324 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800325 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700326 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500327 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500328 std::get_if<uint32_t>(
329 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800330 if (value == nullptr)
331 {
332 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800333 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800334 continue;
335 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500336 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800337 aResp->res.jsonValue
338 ["MemorySummary"]
339 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500340 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800341 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500342 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800343 if (preValue == nullptr)
344 {
345 continue;
346 }
George Liu0fda0f12021-11-16 10:06:17 +0800347 aResp->res.jsonValue
348 ["MemorySummary"]
349 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800350 *value / (1024 * 1024) +
351 *preValue;
352 aResp->res
353 .jsonValue["MemorySummary"]
354 ["Status"]["State"] =
355 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700356 }
Ed Tanous029573d2019-02-01 10:57:49 -0800357 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500358 else
359 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700360 sdbusplus::asio::getProperty<bool>(
361 *crow::connections::systemBus,
362 service, path,
363 "xyz.openbmc_project.State."
364 "Decorator.OperationalStatus",
365 "Functional",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500366 [aResp](
367 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000368 ec3,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700369 bool dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000370 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500371 {
372 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800373 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000374 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500375 return;
376 }
377 updateDimmProperties(aResp,
378 dimmState);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700379 });
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500380 }
Ed Tanous029573d2019-02-01 10:57:49 -0800381 },
382 connection.first, path,
383 "org.freedesktop.DBus.Properties", "GetAll",
384 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700385
386 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800387 }
388 else if (interfaceName ==
389 "xyz.openbmc_project.Inventory.Item.Cpu")
390 {
391 BMCWEB_LOG_DEBUG
392 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500393
Ali Ahmed03fbed92021-09-03 02:33:43 -0500394 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700395
396 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800397 }
398 else if (interfaceName ==
399 "xyz.openbmc_project.Common.UUID")
400 {
401 BMCWEB_LOG_DEBUG
402 << "Found UUID, now get its properties.";
403 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800404 [aResp](const boost::system::error_code ec3,
405 const std::vector<std::pair<
406 std::string,
407 dbus::utility::DbusVariantType>>&
408 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000409 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800410 {
411 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000412 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800413 messages::internalError(aResp->res);
414 return;
415 }
416 BMCWEB_LOG_DEBUG << "Got "
417 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500418 << " UUID properties.";
Ed Tanous168e20c2021-12-13 14:39:53 -0800419 for (const std::pair<
420 std::string,
421 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500422 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800423 {
Ed Tanous029573d2019-02-01 10:57:49 -0800424 if (property.first == "UUID")
425 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500426 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500427 std::get_if<std::string>(
428 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700429
Ed Tanous029573d2019-02-01 10:57:49 -0800430 if (value != nullptr)
431 {
432 std::string valueStr = *value;
433 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700434 {
Ed Tanous029573d2019-02-01 10:57:49 -0800435 valueStr.insert(8, 1, '-');
436 valueStr.insert(13, 1, '-');
437 valueStr.insert(18, 1, '-');
438 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700439 }
Ed Tanous029573d2019-02-01 10:57:49 -0800440 BMCWEB_LOG_DEBUG << "UUID = "
441 << valueStr;
442 aResp->res.jsonValue["UUID"] =
443 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700444 }
445 }
Ed Tanous029573d2019-02-01 10:57:49 -0800446 }
447 },
448 connection.first, path,
449 "org.freedesktop.DBus.Properties", "GetAll",
450 "xyz.openbmc_project.Common.UUID");
451 }
452 else if (interfaceName ==
453 "xyz.openbmc_project.Inventory.Item.System")
454 {
455 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800456 [aResp](const boost::system::error_code ec2,
457 const std::vector<std::pair<
458 std::string,
459 dbus::utility::DbusVariantType>>&
460 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000461 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800462 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700463 // doesn't have to include this
464 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800465 return;
466 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500467 BMCWEB_LOG_DEBUG
468 << "Got " << propertiesList.size()
469 << " properties for system";
Ed Tanous168e20c2021-12-13 14:39:53 -0800470 for (const std::pair<
471 std::string,
472 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500473 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800474 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500475 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600476 property.first;
477 if ((propertyName == "PartNumber") ||
478 (propertyName == "SerialNumber") ||
479 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500480 (propertyName == "Model") ||
481 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800482 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500483 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600484 std::get_if<std::string>(
485 &property.second);
486 if (value != nullptr)
487 {
488 aResp->res
489 .jsonValue[propertyName] =
490 *value;
491 }
Ed Tanous029573d2019-02-01 10:57:49 -0800492 }
493 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500494
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600495 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500496 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600497 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500498 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800499 },
500 connection.first, path,
501 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800502 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700503
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700504 sdbusplus::asio::getProperty<std::string>(
505 *crow::connections::systemBus, connection.first,
506 path,
507 "xyz.openbmc_project.Inventory.Decorator."
508 "AssetTag",
509 "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -0800510 [aResp](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700511 const std::string& value) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000512 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700513 {
514 // doesn't have to include this
515 // interface
516 return;
517 }
518
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700519 aResp->res.jsonValue["AssetTag"] = value;
520 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700521 }
522 }
523 }
524 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700525 },
526 "xyz.openbmc_project.ObjectMapper",
527 "/xyz/openbmc_project/object_mapper",
528 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700529 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500530 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700531 "xyz.openbmc_project.Inventory.Decorator.Asset",
532 "xyz.openbmc_project.Inventory.Item.Cpu",
533 "xyz.openbmc_project.Inventory.Item.Dimm",
534 "xyz.openbmc_project.Inventory.Item.System",
535 "xyz.openbmc_project.Common.UUID",
536 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700537}
538
539/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 * @brief Retrieves host state properties over dbus
541 *
542 * @param[in] aResp Shared pointer for completing asynchronous calls.
543 *
544 * @return None.
545 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800546inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700547{
548 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700549 sdbusplus::asio::getProperty<std::string>(
550 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
551 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
552 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800553 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700554 const std::string& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700555 if (ec)
556 {
557 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700558 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700559 return;
560 }
Ed Tanous66173382018-08-15 18:20:59 -0700561
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700562 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
563 // Verify Host State
564 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700565 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700566 aResp->res.jsonValue["PowerState"] = "On";
567 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700568 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700569 else if (hostState ==
570 "xyz.openbmc_project.State.Host.HostState.Quiesced")
571 {
572 aResp->res.jsonValue["PowerState"] = "On";
573 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
574 }
575 else if (hostState ==
576 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
577 {
578 aResp->res.jsonValue["PowerState"] = "On";
579 aResp->res.jsonValue["Status"]["State"] = "InTest";
580 }
581 else if (
582 hostState ==
583 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
584 {
585 aResp->res.jsonValue["PowerState"] = "PoweringOn";
586 aResp->res.jsonValue["Status"]["State"] = "Starting";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOff";
593 aResp->res.jsonValue["Status"]["State"] = "Disabled";
594 }
595 else
596 {
597 aResp->res.jsonValue["PowerState"] = "Off";
598 aResp->res.jsonValue["Status"]["State"] = "Disabled";
599 }
600 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700601}
602
603/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500604 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530605 *
606 * @param[in] dbusSource The boot source in DBUS speak.
607 *
608 * @return Returns as a string, the boot source in Redfish terms. If translation
609 * cannot be done, returns an empty string.
610 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000611inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530612{
613 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
614 {
615 return "None";
616 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700617 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530618 {
619 return "Hdd";
620 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700621 if (dbusSource ==
622 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530623 {
624 return "Cd";
625 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700626 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530627 {
628 return "Pxe";
629 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700630 if (dbusSource ==
631 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700632 {
633 return "Usb";
634 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700635 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530636}
637
638/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300639 * @brief Translates boot type DBUS property value to redfish.
640 *
641 * @param[in] dbusType The boot type in DBUS speak.
642 *
643 * @return Returns as a string, the boot type in Redfish terms. If translation
644 * cannot be done, returns an empty string.
645 */
646inline std::string dbusToRfBootType(const std::string& dbusType)
647{
648 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
649 {
650 return "Legacy";
651 }
652 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
653 {
654 return "UEFI";
655 }
656 return "";
657}
658
659/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500660 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661 *
662 * @param[in] dbusMode The boot mode in DBUS speak.
663 *
664 * @return Returns as a string, the boot mode in Redfish terms. If translation
665 * cannot be done, returns an empty string.
666 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000667inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668{
669 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
670 {
671 return "None";
672 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700673 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674 {
675 return "Diags";
676 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700677 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530678 {
679 return "BiosSetup";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530682}
683
684/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500685 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530686 *
687 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700688 * @param[out] bootSource The DBus source
689 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530690 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700691 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530692 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800693inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500694 const std::string& rfSource,
695 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530696{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300697 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
698 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700699
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530700 if (rfSource == "None")
701 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700702 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530703 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700704 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530705 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700706 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
707 }
708 else if (rfSource == "Hdd")
709 {
710 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
711 }
712 else if (rfSource == "Diags")
713 {
714 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
715 }
716 else if (rfSource == "Cd")
717 {
718 bootSource =
719 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
720 }
721 else if (rfSource == "BiosSetup")
722 {
723 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530724 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700725 else if (rfSource == "Usb")
726 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700727 bootSource =
728 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700729 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530730 else
731 {
George Liu0fda0f12021-11-16 10:06:17 +0800732 BMCWEB_LOG_DEBUG
733 << "Invalid property value for BootSourceOverrideTarget: "
734 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700735 messages::propertyValueNotInList(aResp->res, rfSource,
736 "BootSourceTargetOverride");
737 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530738 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700739 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530740}
Ali Ahmed19817712021-06-29 17:01:52 -0500741
Andrew Geissler978b8802020-11-19 13:36:40 -0600742/**
743 * @brief Retrieves boot progress of the system
744 *
745 * @param[in] aResp Shared pointer for generating response message.
746 *
747 * @return None.
748 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800749inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600750{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700751 sdbusplus::asio::getProperty<std::string>(
752 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
753 "/xyz/openbmc_project/state/host0",
754 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600755 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700756 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600757 if (ec)
758 {
759 // BootProgress is an optional object so just do nothing if
760 // not found
761 return;
762 }
763
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700764 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600765
766 // Now convert the D-Bus BootProgress to the appropriate Redfish
767 // enum
768 std::string rfBpLastState = "None";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700769 if (bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800770 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified")
Andrew Geissler978b8802020-11-19 13:36:40 -0600771 {
772 rfBpLastState = "None";
773 }
George Liu0fda0f12021-11-16 10:06:17 +0800774 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700775 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800776 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.PrimaryProcInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600777 {
778 rfBpLastState = "PrimaryProcessorInitializationStarted";
779 }
George Liu0fda0f12021-11-16 10:06:17 +0800780 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700781 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800782 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.BusInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600783 {
784 rfBpLastState = "BusInitializationStarted";
785 }
George Liu0fda0f12021-11-16 10:06:17 +0800786 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700787 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800788 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.MemoryInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600789 {
790 rfBpLastState = "MemoryInitializationStarted";
791 }
George Liu0fda0f12021-11-16 10:06:17 +0800792 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700793 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800794 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.SecondaryProcInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600795 {
796 rfBpLastState = "SecondaryProcessorInitializationStarted";
797 }
George Liu0fda0f12021-11-16 10:06:17 +0800798 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700799 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800800 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.PCIInit")
Andrew Geissler978b8802020-11-19 13:36:40 -0600801 {
802 rfBpLastState = "PCIResourceConfigStarted";
803 }
George Liu0fda0f12021-11-16 10:06:17 +0800804 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700805 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800806 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.SystemInitComplete")
Andrew Geissler978b8802020-11-19 13:36:40 -0600807 {
808 rfBpLastState = "SystemHardwareInitializationComplete";
809 }
George Liu0fda0f12021-11-16 10:06:17 +0800810 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700811 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800812 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSStart")
Andrew Geissler978b8802020-11-19 13:36:40 -0600813 {
814 rfBpLastState = "OSBootStarted";
815 }
George Liu0fda0f12021-11-16 10:06:17 +0800816 else if (
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700817 bootProgressStr ==
George Liu0fda0f12021-11-16 10:06:17 +0800818 "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSRunning")
Andrew Geissler978b8802020-11-19 13:36:40 -0600819 {
820 rfBpLastState = "OSRunning";
821 }
822 else
823 {
824 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700825 << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600826 // Just return the default
827 }
828
829 aResp->res.jsonValue["BootProgress"]["LastState"] = rfBpLastState;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700830 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600831}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530832
833/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300834 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300835 *
836 * @param[in] aResp Shared pointer for generating response message.
837 *
838 * @return None.
839 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300840
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300841inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300842{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700843 sdbusplus::asio::getProperty<std::string>(
844 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
845 "/xyz/openbmc_project/control/host0/boot",
846 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300847 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700848 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300849 if (ec)
850 {
851 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300852 return;
853 }
854
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700855 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300856
George Liu0fda0f12021-11-16 10:06:17 +0800857 aResp->res
858 .jsonValue["Boot"]
859 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
860 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300861
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700862 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300863 if (rfType.empty())
864 {
865 messages::internalError(aResp->res);
866 return;
867 }
868
869 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700870 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300871}
872
873/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300874 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530875 *
876 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530877 *
878 * @return None.
879 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300880
881inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530882{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700883 sdbusplus::asio::getProperty<std::string>(
884 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
885 "/xyz/openbmc_project/control/host0/boot",
886 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300887 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700888 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530889 if (ec)
890 {
891 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
892 messages::internalError(aResp->res);
893 return;
894 }
895
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700896 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530897
George Liu0fda0f12021-11-16 10:06:17 +0800898 aResp->res
899 .jsonValue["Boot"]
900 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
901 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530902
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700903 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530904 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
905 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700906 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530907 if (!rfMode.empty())
908 {
909 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
910 rfMode;
911 }
912 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700913 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530914}
915
916/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300917 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530918 *
919 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530920 *
921 * @return None.
922 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300923
924inline void
925 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530926{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700927 sdbusplus::asio::getProperty<std::string>(
928 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
929 "/xyz/openbmc_project/control/host0/boot",
930 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300931 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700932 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933 if (ec)
934 {
935 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
936 messages::internalError(aResp->res);
937 return;
938 }
939
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700940 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530941
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700942 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530943 if (!rfSource.empty())
944 {
945 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
946 rfSource;
947 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300948
949 // Get BootMode as BootSourceOverrideTarget is constructed
950 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300951 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700952 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530953}
954
955/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300956 * @brief This functions abstracts all the logic behind getting a
957 * "BootSourceOverrideEnabled" property from an overall boot override enable
958 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 *
960 * @param[in] aResp Shared pointer for generating response message.
961 *
962 * @return None.
963 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530964
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300965inline void
966 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
967 const bool bootOverrideEnableSetting)
968{
969 if (!bootOverrideEnableSetting)
970 {
971 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
972 return;
973 }
974
975 // If boot source override is enabled, we need to check 'one_time'
976 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700977 sdbusplus::asio::getProperty<bool>(
978 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
979 "/xyz/openbmc_project/control/host0/boot/one_time",
980 "xyz.openbmc_project.Object.Enable", "Enabled",
981 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530982 if (ec)
983 {
984 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300985 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986 return;
987 }
988
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300989 if (oneTimeSetting)
990 {
991 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
992 "Once";
993 }
994 else
995 {
996 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
997 "Continuous";
998 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700999 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000}
1001
1002/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001003 * @brief Retrieves boot override enable over DBUS
1004 *
1005 * @param[in] aResp Shared pointer for generating response message.
1006 *
1007 * @return None.
1008 */
1009
1010inline void
1011 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1012{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001013 sdbusplus::asio::getProperty<bool>(
1014 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1015 "/xyz/openbmc_project/control/host0/boot",
1016 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001017 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001018 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001019 if (ec)
1020 {
1021 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1022 messages::internalError(aResp->res);
1023 return;
1024 }
1025
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001026 processBootOverrideEnable(aResp, bootOverrideEnable);
1027 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001028}
1029
1030/**
1031 * @brief Retrieves boot source override properties
1032 *
1033 * @param[in] aResp Shared pointer for generating response message.
1034 *
1035 * @return None.
1036 */
1037inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1038{
1039 BMCWEB_LOG_DEBUG << "Get boot information.";
1040
1041 getBootOverrideSource(aResp);
1042 getBootOverrideType(aResp);
1043 getBootOverrideEnable(aResp);
1044}
1045
1046/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001047 * @brief Retrieves the Last Reset Time
1048 *
1049 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1050 * and power off. Even though this is the "system" Redfish object look at the
1051 * chassis D-Bus interface for the LastStateChangeTime since this has the
1052 * last power operation time.
1053 *
1054 * @param[in] aResp Shared pointer for generating response message.
1055 *
1056 * @return None.
1057 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001058inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001059{
1060 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1061
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001062 sdbusplus::asio::getProperty<uint64_t>(
1063 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1064 "/xyz/openbmc_project/state/chassis0",
1065 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1066 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001067 if (ec)
1068 {
1069 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1070 return;
1071 }
1072
Gunnar Millsc0557e12020-06-30 11:26:20 -05001073 // LastStateChangeTime is epoch time, in milliseconds
1074 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001075 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001076
1077 // Convert to ISO 8601 standard
1078 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001079 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001080 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001081}
1082
1083/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001084 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1085 *
1086 * @param[in] aResp Shared pointer for generating response message.
1087 *
1088 * @return None.
1089 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001090inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001091{
1092 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1093
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001094 sdbusplus::asio::getProperty<bool>(
1095 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1096 "/xyz/openbmc_project/control/host0/auto_reboot",
1097 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1098 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001099 if (ec)
1100 {
1101 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1102 return;
1103 }
1104
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001105 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1106 if (autoRebootEnabled == true)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001107 {
1108 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1109 "RetryAttempts";
1110 // If AutomaticRetry (AutoReboot) is enabled see how many
1111 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001112 sdbusplus::asio::getProperty<uint32_t>(
1113 *crow::connections::systemBus,
1114 "xyz.openbmc_project.State.Host",
1115 "/xyz/openbmc_project/state/host0",
1116 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1117 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001118 [aResp](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001119 uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001120 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001121 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001122 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001123 return;
1124 }
1125
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001126 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001127 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001128
1129 aResp->res
1130 .jsonValue["Boot"]
1131 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001132 autoRebootAttemptsLeft;
1133 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001134 }
1135 else
1136 {
1137 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1138 "Disabled";
1139 }
1140
1141 // Not on D-Bus. Hardcoded here:
1142 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1143 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001144
1145 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1146 // and RetryAttempts. OpenBMC only supports Disabled and
1147 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001148 aResp->res
1149 .jsonValue["Boot"]
1150 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1151 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001152 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001153}
1154
1155/**
George Liuc6a620f2020-04-10 17:18:11 +08001156 * @brief Retrieves power restore policy over DBUS.
1157 *
1158 * @param[in] aResp Shared pointer for generating response message.
1159 *
1160 * @return None.
1161 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001162inline void
1163 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001164{
1165 BMCWEB_LOG_DEBUG << "Get power restore policy";
1166
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001167 sdbusplus::asio::getProperty<std::string>(
1168 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1169 "/xyz/openbmc_project/control/host0/power_restore_policy",
1170 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1171 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001172 if (ec)
1173 {
1174 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1175 return;
1176 }
1177
George Liu0fda0f12021-11-16 10:06:17 +08001178 const boost::container::flat_map<std::string, std::string> policyMaps = {
1179 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1180 "AlwaysOn"},
1181 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1182 "AlwaysOff"},
1183 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1184 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001185
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001186 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001187 if (policyMapsIt == policyMaps.end())
1188 {
1189 messages::internalError(aResp->res);
1190 return;
1191 }
1192
1193 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001194 });
George Liuc6a620f2020-04-10 17:18:11 +08001195}
1196
1197/**
Ali Ahmed19817712021-06-29 17:01:52 -05001198 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1199 * TPM is required for booting the host.
1200 *
1201 * @param[in] aResp Shared pointer for generating response message.
1202 *
1203 * @return None.
1204 */
1205inline void getTrustedModuleRequiredToBoot(
1206 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1207{
1208 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1209
1210 crow::connections::systemBus->async_method_call(
1211 [aResp](
1212 const boost::system::error_code ec,
1213 std::vector<std::pair<
1214 std::string,
1215 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1216 subtree) {
1217 if (ec)
1218 {
1219 BMCWEB_LOG_DEBUG
1220 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1221 // This is an optional D-Bus object so just return if
1222 // error occurs
1223 return;
1224 }
1225 if (subtree.size() == 0)
1226 {
1227 // As noted above, this is an optional interface so just return
1228 // if there is no instance found
1229 return;
1230 }
1231
1232 /* When there is more than one TPMEnable object... */
1233 if (subtree.size() > 1)
1234 {
1235 BMCWEB_LOG_DEBUG
1236 << "DBUS response has more than 1 TPM Enable object:"
1237 << subtree.size();
1238 // Throw an internal Error and return
1239 messages::internalError(aResp->res);
1240 return;
1241 }
1242
1243 // Make sure the Dbus response map has a service and objectPath
1244 // field
1245 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1246 {
1247 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1248 messages::internalError(aResp->res);
1249 return;
1250 }
1251
1252 const std::string& path = subtree[0].first;
1253 const std::string& serv = subtree[0].second.begin()->first;
1254
1255 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001256 sdbusplus::asio::getProperty<bool>(
1257 *crow::connections::systemBus, serv, path,
1258 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1259 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001260 if (ec)
1261 {
1262 BMCWEB_LOG_DEBUG
1263 << "D-BUS response error on TPM.Policy Get" << ec;
1264 messages::internalError(aResp->res);
1265 return;
1266 }
1267
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001268 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001269 {
1270 aResp->res
1271 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1272 "Required";
1273 }
1274 else
1275 {
1276 aResp->res
1277 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1278 "Disabled";
1279 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001280 });
Ali Ahmed19817712021-06-29 17:01:52 -05001281 },
1282 "xyz.openbmc_project.ObjectMapper",
1283 "/xyz/openbmc_project/object_mapper",
1284 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1285 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1286}
1287
1288/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001289 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1290 * TPM is required for booting the host.
1291 *
1292 * @param[in] aResp Shared pointer for generating response message.
1293 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1294 *
1295 * @return None.
1296 */
1297inline void setTrustedModuleRequiredToBoot(
1298 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1299{
1300 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1301
1302 crow::connections::systemBus->async_method_call(
1303 [aResp, tpmRequired](
1304 const boost::system::error_code ec,
1305 std::vector<std::pair<
1306 std::string,
1307 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1308 subtree) {
1309 if (ec)
1310 {
1311 BMCWEB_LOG_DEBUG
1312 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1313 messages::internalError(aResp->res);
1314 return;
1315 }
1316 if (subtree.size() == 0)
1317 {
1318 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1319 "TrustedModuleRequiredToBoot");
1320 return;
1321 }
1322
1323 /* When there is more than one TPMEnable object... */
1324 if (subtree.size() > 1)
1325 {
1326 BMCWEB_LOG_DEBUG
1327 << "DBUS response has more than 1 TPM Enable object:"
1328 << subtree.size();
1329 // Throw an internal Error and return
1330 messages::internalError(aResp->res);
1331 return;
1332 }
1333
1334 // Make sure the Dbus response map has a service and objectPath
1335 // field
1336 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1337 {
1338 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1339 messages::internalError(aResp->res);
1340 return;
1341 }
1342
1343 const std::string& path = subtree[0].first;
1344 const std::string& serv = subtree[0].second.begin()->first;
1345
1346 if (serv.empty())
1347 {
1348 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1349 messages::internalError(aResp->res);
1350 return;
1351 }
1352
1353 // Valid TPM Enable object found, now setting the value
1354 crow::connections::systemBus->async_method_call(
1355 [aResp](const boost::system::error_code ec) {
1356 if (ec)
1357 {
George Liu0fda0f12021-11-16 10:06:17 +08001358 BMCWEB_LOG_DEBUG
1359 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1360 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001361 messages::internalError(aResp->res);
1362 return;
1363 }
1364 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1365 },
1366 serv, path, "org.freedesktop.DBus.Properties", "Set",
1367 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001368 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001369 },
1370 "xyz.openbmc_project.ObjectMapper",
1371 "/xyz/openbmc_project/object_mapper",
1372 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1373 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1374}
1375
1376/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301377 * @brief Sets boot properties into DBUS object(s).
1378 *
1379 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001380 * @param[in] bootType The boot type to set.
1381 * @return Integer error code.
1382 */
1383inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001384 const std::optional<std::string>& bootType)
1385{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001386 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001387
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001388 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001389 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001390 return;
1391 }
1392
1393 // Source target specified
1394 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1395 // Figure out which DBUS interface and property to use
1396 if (*bootType == "Legacy")
1397 {
1398 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1399 }
1400 else if (*bootType == "UEFI")
1401 {
1402 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1403 }
1404 else
1405 {
1406 BMCWEB_LOG_DEBUG << "Invalid property value for "
1407 "BootSourceOverrideMode: "
1408 << *bootType;
1409 messages::propertyValueNotInList(aResp->res, *bootType,
1410 "BootSourceOverrideMode");
1411 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001412 }
1413
1414 // Act on validated parameters
1415 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1416
1417 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001418 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001419 if (ec)
1420 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001421 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1422 if (ec.value() == boost::asio::error::host_unreachable)
1423 {
1424 messages::resourceNotFound(aResp->res, "Set", "BootType");
1425 return;
1426 }
1427 messages::internalError(aResp->res);
1428 return;
1429 }
1430 BMCWEB_LOG_DEBUG << "Boot type update done.";
1431 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001432 "xyz.openbmc_project.Settings",
1433 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001434 "org.freedesktop.DBus.Properties", "Set",
1435 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001436 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001437}
1438
1439/**
1440 * @brief Sets boot properties into DBUS object(s).
1441 *
1442 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001443 * @param[in] bootType The boot type to set.
1444 * @return Integer error code.
1445 */
1446inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1447 const std::optional<std::string>& bootEnable)
1448{
1449 if (!bootEnable)
1450 {
1451 return;
1452 }
1453 // Source target specified
1454 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1455
1456 bool bootOverrideEnable = false;
1457 bool bootOverridePersistent = false;
1458 // Figure out which DBUS interface and property to use
1459 if (*bootEnable == "Disabled")
1460 {
1461 bootOverrideEnable = false;
1462 }
1463 else if (*bootEnable == "Once")
1464 {
1465 bootOverrideEnable = true;
1466 bootOverridePersistent = false;
1467 }
1468 else if (*bootEnable == "Continuous")
1469 {
1470 bootOverrideEnable = true;
1471 bootOverridePersistent = true;
1472 }
1473 else
1474 {
George Liu0fda0f12021-11-16 10:06:17 +08001475 BMCWEB_LOG_DEBUG
1476 << "Invalid property value for BootSourceOverrideEnabled: "
1477 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001478 messages::propertyValueNotInList(aResp->res, *bootEnable,
1479 "BootSourceOverrideEnabled");
1480 return;
1481 }
1482
1483 // Act on validated parameters
1484 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1485
1486 crow::connections::systemBus->async_method_call(
1487 [aResp](const boost::system::error_code ec) {
1488 if (ec)
1489 {
1490 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1491 messages::internalError(aResp->res);
1492 return;
1493 }
1494 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1495 },
1496 "xyz.openbmc_project.Settings",
1497 "/xyz/openbmc_project/control/host0/boot",
1498 "org.freedesktop.DBus.Properties", "Set",
1499 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001500 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001501
1502 if (!bootOverrideEnable)
1503 {
1504 return;
1505 }
1506
1507 // In case boot override is enabled we need to set correct value for the
1508 // 'one_time' enable DBus interface
1509 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1510 << bootOverridePersistent;
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 one_time update done.";
1521 },
1522 "xyz.openbmc_project.Settings",
1523 "/xyz/openbmc_project/control/host0/boot/one_time",
1524 "org.freedesktop.DBus.Properties", "Set",
1525 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001526 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001527}
1528
1529/**
1530 * @brief Sets boot properties into DBUS object(s).
1531 *
1532 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301533 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301534 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001535 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301536 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001537inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001538 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301539{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001540 std::string bootSourceStr;
1541 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001542
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001543 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301544 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001545 return;
1546 }
1547
1548 // Source target specified
1549 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1550 // Figure out which DBUS interface and property to use
1551 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr))
1552 {
1553 BMCWEB_LOG_DEBUG
1554 << "Invalid property value for BootSourceOverrideTarget: "
1555 << *bootSource;
1556 messages::propertyValueNotInList(aResp->res, *bootSource,
1557 "BootSourceTargetOverride");
1558 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001559 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301560
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001561 // Act on validated parameters
1562 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1563 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001564
1565 crow::connections::systemBus->async_method_call(
1566 [aResp](const boost::system::error_code ec) {
1567 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301568 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001569 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1570 messages::internalError(aResp->res);
1571 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301572 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001573 BMCWEB_LOG_DEBUG << "Boot source update done.";
1574 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001575 "xyz.openbmc_project.Settings",
1576 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001577 "org.freedesktop.DBus.Properties", "Set",
1578 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001579 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001580
1581 crow::connections::systemBus->async_method_call(
1582 [aResp](const boost::system::error_code ec) {
1583 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301584 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001585 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1586 messages::internalError(aResp->res);
1587 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301588 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001589 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1590 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001591 "xyz.openbmc_project.Settings",
1592 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001593 "org.freedesktop.DBus.Properties", "Set",
1594 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001595 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001596}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001597
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001598/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001599 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301600 *
1601 * @param[in] aResp Shared pointer for generating response message.
1602 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001603 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301604 * @param[in] bootEnable The boot override enable from incoming RF request.
1605 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001606 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301607 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001608
1609inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1610 const std::optional<std::string>& bootSource,
1611 const std::optional<std::string>& bootType,
1612 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301613{
1614 BMCWEB_LOG_DEBUG << "Set boot information.";
1615
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001616 setBootModeOrSource(aResp, bootSource);
1617 setBootType(aResp, bootType);
1618 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301619}
1620
George Liuc6a620f2020-04-10 17:18:11 +08001621/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001622 * @brief Sets AssetTag
1623 *
1624 * @param[in] aResp Shared pointer for generating response message.
1625 * @param[in] assetTag "AssetTag" from request.
1626 *
1627 * @return None.
1628 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001629inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001630 const std::string& assetTag)
1631{
1632 crow::connections::systemBus->async_method_call(
1633 [aResp, assetTag](
1634 const boost::system::error_code ec,
1635 const std::vector<std::pair<
1636 std::string,
1637 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1638 subtree) {
1639 if (ec)
1640 {
1641 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1642 messages::internalError(aResp->res);
1643 return;
1644 }
1645 if (subtree.size() == 0)
1646 {
1647 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1648 messages::internalError(aResp->res);
1649 return;
1650 }
1651 // Assume only 1 system D-Bus object
1652 // Throw an error if there is more than 1
1653 if (subtree.size() > 1)
1654 {
1655 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1656 messages::internalError(aResp->res);
1657 return;
1658 }
1659 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1660 {
1661 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1662 messages::internalError(aResp->res);
1663 return;
1664 }
1665
1666 const std::string& path = subtree[0].first;
1667 const std::string& service = subtree[0].second.begin()->first;
1668
1669 if (service.empty())
1670 {
1671 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1672 messages::internalError(aResp->res);
1673 return;
1674 }
1675
1676 crow::connections::systemBus->async_method_call(
1677 [aResp](const boost::system::error_code ec2) {
1678 if (ec2)
1679 {
1680 BMCWEB_LOG_DEBUG
1681 << "D-Bus response error on AssetTag Set " << ec2;
1682 messages::internalError(aResp->res);
1683 return;
1684 }
1685 },
1686 service, path, "org.freedesktop.DBus.Properties", "Set",
1687 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001688 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001689 },
1690 "xyz.openbmc_project.ObjectMapper",
1691 "/xyz/openbmc_project/object_mapper",
1692 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1693 "/xyz/openbmc_project/inventory", int32_t(0),
1694 std::array<const char*, 1>{
1695 "xyz.openbmc_project.Inventory.Item.System"});
1696}
1697
1698/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001699 * @brief Sets automaticRetry (Auto Reboot)
1700 *
1701 * @param[in] aResp Shared pointer for generating response message.
1702 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1703 *
1704 * @return None.
1705 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001706inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001707 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001708{
1709 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1710
1711 // OpenBMC only supports "Disabled" and "RetryAttempts".
1712 bool autoRebootEnabled;
1713
1714 if (automaticRetryConfig == "Disabled")
1715 {
1716 autoRebootEnabled = false;
1717 }
1718 else if (automaticRetryConfig == "RetryAttempts")
1719 {
1720 autoRebootEnabled = true;
1721 }
1722 else
1723 {
George Liu0fda0f12021-11-16 10:06:17 +08001724 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001725 << automaticRetryConfig;
1726 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1727 "AutomaticRetryConfig");
1728 return;
1729 }
1730
1731 crow::connections::systemBus->async_method_call(
1732 [aResp](const boost::system::error_code ec) {
1733 if (ec)
1734 {
1735 messages::internalError(aResp->res);
1736 return;
1737 }
1738 },
1739 "xyz.openbmc_project.Settings",
1740 "/xyz/openbmc_project/control/host0/auto_reboot",
1741 "org.freedesktop.DBus.Properties", "Set",
1742 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001743 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001744}
1745
1746/**
George Liuc6a620f2020-04-10 17:18:11 +08001747 * @brief Sets power restore policy properties.
1748 *
1749 * @param[in] aResp Shared pointer for generating response message.
1750 * @param[in] policy power restore policy properties from request.
1751 *
1752 * @return None.
1753 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001754inline void
1755 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1756 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001757{
1758 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1759
1760 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001761 {"AlwaysOn",
1762 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1763 {"AlwaysOff",
1764 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1765 {"LastState",
1766 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001767
1768 std::string powerRestorPolicy;
1769
Gunnar Mills4e69c902021-01-05 19:50:11 -06001770 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001771 if (policyMapsIt == policyMaps.end())
1772 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001773 messages::propertyValueNotInList(aResp->res, policy,
1774 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001775 return;
1776 }
1777
1778 powerRestorPolicy = policyMapsIt->second;
1779
1780 crow::connections::systemBus->async_method_call(
1781 [aResp](const boost::system::error_code ec) {
1782 if (ec)
1783 {
1784 messages::internalError(aResp->res);
1785 return;
1786 }
1787 },
1788 "xyz.openbmc_project.Settings",
1789 "/xyz/openbmc_project/control/host0/power_restore_policy",
1790 "org.freedesktop.DBus.Properties", "Set",
1791 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001792 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001793}
1794
AppaRao Pulia6349912019-10-18 17:16:08 +05301795#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1796/**
1797 * @brief Retrieves provisioning status
1798 *
1799 * @param[in] aResp Shared pointer for completing asynchronous calls.
1800 *
1801 * @return None.
1802 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001803inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301804{
1805 BMCWEB_LOG_DEBUG << "Get OEM information.";
1806 crow::connections::systemBus->async_method_call(
1807 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001808 const std::vector<std::pair<std::string, VariantType>>&
1809 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301810 nlohmann::json& oemPFR =
1811 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001812 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1813 "#OemComputerSystem.OpenBmc";
1814 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1815
AppaRao Pulia6349912019-10-18 17:16:08 +05301816 if (ec)
1817 {
1818 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301819 // not an error, don't have to have the interface
1820 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301821 return;
1822 }
1823
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001824 const bool* provState = nullptr;
1825 const bool* lockState = nullptr;
1826 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301827 propertiesList)
1828 {
1829 if (property.first == "UfmProvisioned")
1830 {
1831 provState = std::get_if<bool>(&property.second);
1832 }
1833 else if (property.first == "UfmLocked")
1834 {
1835 lockState = std::get_if<bool>(&property.second);
1836 }
1837 }
1838
1839 if ((provState == nullptr) || (lockState == nullptr))
1840 {
1841 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1842 messages::internalError(aResp->res);
1843 return;
1844 }
1845
AppaRao Pulia6349912019-10-18 17:16:08 +05301846 if (*provState == true)
1847 {
1848 if (*lockState == true)
1849 {
1850 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1851 }
1852 else
1853 {
1854 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1855 }
1856 }
1857 else
1858 {
1859 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1860 }
1861 },
1862 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1863 "org.freedesktop.DBus.Properties", "GetAll",
1864 "xyz.openbmc_project.PFR.Attributes");
1865}
1866#endif
1867
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301868/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001869 * @brief Translate the PowerMode to a response message.
1870 *
1871 * @param[in] aResp Shared pointer for generating response message.
1872 * @param[in] modeValue PowerMode value to be translated
1873 *
1874 * @return None.
1875 */
1876inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1877 const std::string& modeValue)
1878{
1879 std::string modeString;
1880
George Liu0fda0f12021-11-16 10:06:17 +08001881 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001882 {
1883 aResp->res.jsonValue["PowerMode"] = "Static";
1884 }
George Liu0fda0f12021-11-16 10:06:17 +08001885 else if (
1886 modeValue ==
1887 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001888 {
1889 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1890 }
George Liu0fda0f12021-11-16 10:06:17 +08001891 else if (modeValue ==
1892 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001893 {
1894 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1895 }
George Liu0fda0f12021-11-16 10:06:17 +08001896 else if (modeValue ==
1897 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001898 {
1899 aResp->res.jsonValue["PowerMode"] = "OEM";
1900 }
1901 else
1902 {
1903 // Any other values would be invalid
1904 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1905 messages::internalError(aResp->res);
1906 }
1907}
1908
1909/**
1910 * @brief Retrieves system power mode
1911 *
1912 * @param[in] aResp Shared pointer for generating response message.
1913 *
1914 * @return None.
1915 */
1916inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1917{
1918 BMCWEB_LOG_DEBUG << "Get power mode.";
1919
1920 // Get Power Mode object path:
1921 crow::connections::systemBus->async_method_call(
1922 [aResp](
1923 const boost::system::error_code ec,
1924 const std::vector<std::pair<
1925 std::string,
1926 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1927 subtree) {
1928 if (ec)
1929 {
1930 BMCWEB_LOG_DEBUG
1931 << "DBUS response error on Power.Mode GetSubTree " << ec;
1932 // This is an optional D-Bus object so just return if
1933 // error occurs
1934 return;
1935 }
1936 if (subtree.empty())
1937 {
1938 // As noted above, this is an optional interface so just return
1939 // if there is no instance found
1940 return;
1941 }
1942 if (subtree.size() > 1)
1943 {
1944 // More then one PowerMode object is not supported and is an
1945 // error
1946 BMCWEB_LOG_DEBUG
1947 << "Found more than 1 system D-Bus Power.Mode objects: "
1948 << subtree.size();
1949 messages::internalError(aResp->res);
1950 return;
1951 }
1952 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1953 {
1954 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1955 messages::internalError(aResp->res);
1956 return;
1957 }
1958 const std::string& path = subtree[0].first;
1959 const std::string& service = subtree[0].second.begin()->first;
1960 if (service.empty())
1961 {
1962 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1963 messages::internalError(aResp->res);
1964 return;
1965 }
1966 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001967 sdbusplus::asio::getProperty<std::string>(
1968 *crow::connections::systemBus, service, path,
1969 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001970 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001971 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001972 if (ec)
1973 {
1974 BMCWEB_LOG_DEBUG
1975 << "DBUS response error on PowerMode Get: " << ec;
1976 messages::internalError(aResp->res);
1977 return;
1978 }
1979
Chris Cain3a2d04242021-05-28 16:57:10 -05001980 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
1981 {"Static", "MaximumPerformance", "PowerSaving"};
1982
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001983 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1984 translatePowerMode(aResp, pmode);
1985 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001986 },
1987 "xyz.openbmc_project.ObjectMapper",
1988 "/xyz/openbmc_project/object_mapper",
1989 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1990 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1991}
1992
1993/**
1994 * @brief Validate the specified mode is valid and return the PowerMode
1995 * name associated with that string
1996 *
1997 * @param[in] aResp Shared pointer for generating response message.
1998 * @param[in] modeString String representing the desired PowerMode
1999 *
2000 * @return PowerMode value or empty string if mode is not valid
2001 */
2002inline std::string
2003 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2004 const std::string& modeString)
2005{
2006 std::string mode;
2007
2008 if (modeString == "Static")
2009 {
2010 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2011 }
2012 else if (modeString == "MaximumPerformance")
2013 {
George Liu0fda0f12021-11-16 10:06:17 +08002014 mode =
2015 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002016 }
2017 else if (modeString == "PowerSaving")
2018 {
2019 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2020 }
2021 else
2022 {
2023 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2024 }
2025 return mode;
2026}
2027
2028/**
2029 * @brief Sets system power mode.
2030 *
2031 * @param[in] aResp Shared pointer for generating response message.
2032 * @param[in] pmode System power mode from request.
2033 *
2034 * @return None.
2035 */
2036inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2037 const std::string& pmode)
2038{
2039 BMCWEB_LOG_DEBUG << "Set power mode.";
2040
2041 std::string powerMode = validatePowerMode(aResp, pmode);
2042 if (powerMode.empty())
2043 {
2044 return;
2045 }
2046
2047 // Get Power Mode object path:
2048 crow::connections::systemBus->async_method_call(
2049 [aResp, powerMode](
2050 const boost::system::error_code ec,
2051 const std::vector<std::pair<
2052 std::string,
2053 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2054 subtree) {
2055 if (ec)
2056 {
2057 BMCWEB_LOG_DEBUG
2058 << "DBUS response error on Power.Mode GetSubTree " << ec;
2059 // This is an optional D-Bus object, but user attempted to patch
2060 messages::internalError(aResp->res);
2061 return;
2062 }
2063 if (subtree.empty())
2064 {
2065 // This is an optional D-Bus object, but user attempted to patch
2066 messages::resourceNotFound(aResp->res, "ComputerSystem",
2067 "PowerMode");
2068 return;
2069 }
2070 if (subtree.size() > 1)
2071 {
2072 // More then one PowerMode object is not supported and is an
2073 // error
2074 BMCWEB_LOG_DEBUG
2075 << "Found more than 1 system D-Bus Power.Mode objects: "
2076 << subtree.size();
2077 messages::internalError(aResp->res);
2078 return;
2079 }
2080 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2081 {
2082 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2083 messages::internalError(aResp->res);
2084 return;
2085 }
2086 const std::string& path = subtree[0].first;
2087 const std::string& service = subtree[0].second.begin()->first;
2088 if (service.empty())
2089 {
2090 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2091 messages::internalError(aResp->res);
2092 return;
2093 }
2094
2095 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2096 << path;
2097
2098 // Set the Power Mode property
2099 crow::connections::systemBus->async_method_call(
2100 [aResp](const boost::system::error_code ec) {
2101 if (ec)
2102 {
2103 messages::internalError(aResp->res);
2104 return;
2105 }
2106 },
2107 service, path, "org.freedesktop.DBus.Properties", "Set",
2108 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002109 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002110 },
2111 "xyz.openbmc_project.ObjectMapper",
2112 "/xyz/openbmc_project/object_mapper",
2113 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2114 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2115}
2116
2117/**
Yong Li51709ff2019-09-30 14:13:04 +08002118 * @brief Translates watchdog timeout action DBUS property value to redfish.
2119 *
2120 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2121 *
2122 * @return Returns as a string, the timeout action in Redfish terms. If
2123 * translation cannot be done, returns an empty string.
2124 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002125inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002126{
2127 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2128 {
2129 return "None";
2130 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002131 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002132 {
2133 return "ResetSystem";
2134 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002135 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002136 {
2137 return "PowerDown";
2138 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002139 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002140 {
2141 return "PowerCycle";
2142 }
2143
2144 return "";
2145}
2146
2147/**
Yong Lic45f0082019-10-10 14:19:01 +08002148 *@brief Translates timeout action from Redfish to DBUS property value.
2149 *
2150 *@param[in] rfAction The timeout action in Redfish.
2151 *
2152 *@return Returns as a string, the time_out action as expected by DBUS.
2153 *If translation cannot be done, returns an empty string.
2154 */
2155
Ed Tanous23a21a12020-07-25 04:45:05 +00002156inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002157{
2158 if (rfAction == "None")
2159 {
2160 return "xyz.openbmc_project.State.Watchdog.Action.None";
2161 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002162 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002163 {
2164 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002167 {
2168 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002170 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002171 {
2172 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2173 }
2174
2175 return "";
2176}
2177
2178/**
Yong Li51709ff2019-09-30 14:13:04 +08002179 * @brief Retrieves host watchdog timer properties over DBUS
2180 *
2181 * @param[in] aResp Shared pointer for completing asynchronous calls.
2182 *
2183 * @return None.
2184 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002185inline void
2186 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002187{
2188 BMCWEB_LOG_DEBUG << "Get host watchodg";
2189 crow::connections::systemBus->async_method_call(
2190 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002191 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002192 if (ec)
2193 {
2194 // watchdog service is stopped
2195 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2196 return;
2197 }
2198
2199 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2200
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002201 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002202 aResp->res.jsonValue["HostWatchdogTimer"];
2203
2204 // watchdog service is running/enabled
2205 hostWatchdogTimer["Status"]["State"] = "Enabled";
2206
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002207 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002208 {
2209 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2210 if (property.first == "Enabled")
2211 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002212 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002213
2214 if (!state)
2215 {
2216 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002217 return;
Yong Li51709ff2019-09-30 14:13:04 +08002218 }
2219
2220 hostWatchdogTimer["FunctionEnabled"] = *state;
2221 }
2222 else if (property.first == "ExpireAction")
2223 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002224 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002225 std::get_if<std::string>(&property.second);
2226 if (!s)
2227 {
2228 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002229 return;
Yong Li51709ff2019-09-30 14:13:04 +08002230 }
2231
2232 std::string action = dbusToRfWatchdogAction(*s);
2233 if (action.empty())
2234 {
2235 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002236 return;
Yong Li51709ff2019-09-30 14:13:04 +08002237 }
2238 hostWatchdogTimer["TimeoutAction"] = action;
2239 }
2240 }
2241 },
2242 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2243 "org.freedesktop.DBus.Properties", "GetAll",
2244 "xyz.openbmc_project.State.Watchdog");
2245}
2246
2247/**
Yong Lic45f0082019-10-10 14:19:01 +08002248 * @brief Sets Host WatchDog Timer properties.
2249 *
2250 * @param[in] aResp Shared pointer for generating response message.
2251 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2252 * RF request.
2253 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2254 *
2255 * @return None.
2256 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002257inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002258 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002259 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002260{
2261 BMCWEB_LOG_DEBUG << "Set host watchdog";
2262
2263 if (wdtTimeOutAction)
2264 {
2265 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2266 // check if TimeOut Action is Valid
2267 if (wdtTimeOutActStr.empty())
2268 {
2269 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2270 << *wdtTimeOutAction;
2271 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2272 "TimeoutAction");
2273 return;
2274 }
2275
2276 crow::connections::systemBus->async_method_call(
2277 [aResp](const boost::system::error_code ec) {
2278 if (ec)
2279 {
2280 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2281 messages::internalError(aResp->res);
2282 return;
2283 }
2284 },
2285 "xyz.openbmc_project.Watchdog",
2286 "/xyz/openbmc_project/watchdog/host0",
2287 "org.freedesktop.DBus.Properties", "Set",
2288 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002289 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002290 }
2291
2292 if (wdtEnable)
2293 {
2294 crow::connections::systemBus->async_method_call(
2295 [aResp](const boost::system::error_code ec) {
2296 if (ec)
2297 {
2298 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2299 messages::internalError(aResp->res);
2300 return;
2301 }
2302 },
2303 "xyz.openbmc_project.Watchdog",
2304 "/xyz/openbmc_project/watchdog/host0",
2305 "org.freedesktop.DBus.Properties", "Set",
2306 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002307 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002308 }
2309}
2310
Chris Cain37bbf982021-09-20 10:53:09 -05002311using ipsPropertiesType =
2312 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2313/**
2314 * @brief Parse the Idle Power Saver properties into json
2315 *
2316 * @param[in] aResp Shared pointer for completing asynchronous calls.
2317 * @param[in] properties IPS property data from DBus.
2318 *
2319 * @return true if successful
2320 */
Ed Tanousf6674222021-11-13 09:41:41 -08002321inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2322 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002323{
2324 for (const auto& property : properties)
2325 {
2326 if (property.first == "Enabled")
2327 {
2328 const bool* state = std::get_if<bool>(&property.second);
2329 if (!state)
2330 {
2331 return false;
2332 }
2333 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2334 }
2335 else if (property.first == "EnterUtilizationPercent")
2336 {
2337 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2338 if (!util)
2339 {
2340 return false;
2341 }
2342 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2343 }
2344 else if (property.first == "EnterDwellTime")
2345 {
2346 // Convert Dbus time from milliseconds to seconds
2347 const uint64_t* timeMilliseconds =
2348 std::get_if<uint64_t>(&property.second);
2349 if (!timeMilliseconds)
2350 {
2351 return false;
2352 }
2353 const std::chrono::duration<uint64_t, std::milli> ms(
2354 *timeMilliseconds);
2355 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2356 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2357 .count();
2358 }
2359 else if (property.first == "ExitUtilizationPercent")
2360 {
2361 const uint8_t* util = std::get_if<uint8_t>(&property.second);
2362 if (!util)
2363 {
2364 return false;
2365 }
2366 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2367 }
2368 else if (property.first == "ExitDwellTime")
2369 {
2370 // Convert Dbus time from milliseconds to seconds
2371 const uint64_t* timeMilliseconds =
2372 std::get_if<uint64_t>(&property.second);
2373 if (!timeMilliseconds)
2374 {
2375 return false;
2376 }
2377 const std::chrono::duration<uint64_t, std::milli> ms(
2378 *timeMilliseconds);
2379 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2380 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2381 .count();
2382 }
2383 else
2384 {
2385 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2386 << property.first;
2387 }
2388 }
2389
2390 return true;
2391}
2392
2393/**
2394 * @brief Retrieves host watchdog timer properties over DBUS
2395 *
2396 * @param[in] aResp Shared pointer for completing asynchronous calls.
2397 *
2398 * @return None.
2399 */
2400inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2401{
2402 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2403
2404 // Get IdlePowerSaver object path:
2405 crow::connections::systemBus->async_method_call(
2406 [aResp](
2407 const boost::system::error_code ec,
2408 const std::vector<std::pair<
2409 std::string,
2410 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2411 subtree) {
2412 if (ec)
2413 {
2414 BMCWEB_LOG_DEBUG
2415 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2416 << ec;
2417 messages::internalError(aResp->res);
2418 return;
2419 }
2420 if (subtree.empty())
2421 {
2422 // This is an optional interface so just return
2423 // if there is no instance found
2424 BMCWEB_LOG_DEBUG << "No instances found";
2425 return;
2426 }
2427 if (subtree.size() > 1)
2428 {
2429 // More then one PowerIdlePowerSaver object is not supported and
2430 // is an error
2431 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2432 "Power.IdlePowerSaver objects: "
2433 << subtree.size();
2434 messages::internalError(aResp->res);
2435 return;
2436 }
2437 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2438 {
2439 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2440 messages::internalError(aResp->res);
2441 return;
2442 }
2443 const std::string& path = subtree[0].first;
2444 const std::string& service = subtree[0].second.begin()->first;
2445 if (service.empty())
2446 {
2447 BMCWEB_LOG_DEBUG
2448 << "Power.IdlePowerSaver service mapper error!";
2449 messages::internalError(aResp->res);
2450 return;
2451 }
2452
2453 // Valid IdlePowerSaver object found, now read the current values
2454 crow::connections::systemBus->async_method_call(
2455 [aResp](const boost::system::error_code ec,
2456 ipsPropertiesType& properties) {
2457 if (ec)
2458 {
2459 BMCWEB_LOG_ERROR
2460 << "DBUS response error on IdlePowerSaver GetAll: "
2461 << ec;
2462 messages::internalError(aResp->res);
2463 return;
2464 }
2465
2466 if (parseIpsProperties(aResp, properties) == false)
2467 {
2468 messages::internalError(aResp->res);
2469 return;
2470 }
2471 },
2472 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2473 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2474 },
2475 "xyz.openbmc_project.ObjectMapper",
2476 "/xyz/openbmc_project/object_mapper",
2477 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2478 std::array<const char*, 1>{
2479 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2480
2481 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2482}
2483
2484/**
2485 * @brief Sets Idle Power Saver properties.
2486 *
2487 * @param[in] aResp Shared pointer for generating response message.
2488 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2489 * RF request.
2490 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2491 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2492 * before entering idle state.
2493 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2494 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2495 * before exiting idle state
2496 *
2497 * @return None.
2498 */
2499inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2500 const std::optional<bool> ipsEnable,
2501 const std::optional<uint8_t> ipsEnterUtil,
2502 const std::optional<uint64_t> ipsEnterTime,
2503 const std::optional<uint8_t> ipsExitUtil,
2504 const std::optional<uint64_t> ipsExitTime)
2505{
2506 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2507
2508 // Get IdlePowerSaver object path:
2509 crow::connections::systemBus->async_method_call(
2510 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2511 ipsExitTime](
2512 const boost::system::error_code ec,
2513 const std::vector<std::pair<
2514 std::string,
2515 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2516 subtree) {
2517 if (ec)
2518 {
2519 BMCWEB_LOG_DEBUG
2520 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2521 << ec;
2522 messages::internalError(aResp->res);
2523 return;
2524 }
2525 if (subtree.empty())
2526 {
2527 // This is an optional D-Bus object, but user attempted to patch
2528 messages::resourceNotFound(aResp->res, "ComputerSystem",
2529 "IdlePowerSaver");
2530 return;
2531 }
2532 if (subtree.size() > 1)
2533 {
2534 // More then one PowerIdlePowerSaver object is not supported and
2535 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002536 BMCWEB_LOG_DEBUG
2537 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2538 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002539 messages::internalError(aResp->res);
2540 return;
2541 }
2542 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2543 {
2544 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2545 messages::internalError(aResp->res);
2546 return;
2547 }
2548 const std::string& path = subtree[0].first;
2549 const std::string& service = subtree[0].second.begin()->first;
2550 if (service.empty())
2551 {
2552 BMCWEB_LOG_DEBUG
2553 << "Power.IdlePowerSaver service mapper error!";
2554 messages::internalError(aResp->res);
2555 return;
2556 }
2557
2558 // Valid Power IdlePowerSaver object found, now set any values that
2559 // need to be updated
2560
2561 if (ipsEnable)
2562 {
2563 crow::connections::systemBus->async_method_call(
2564 [aResp](const boost::system::error_code ec) {
2565 if (ec)
2566 {
2567 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2568 messages::internalError(aResp->res);
2569 return;
2570 }
2571 },
2572 service, path, "org.freedesktop.DBus.Properties", "Set",
2573 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002574 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002575 }
2576 if (ipsEnterUtil)
2577 {
2578 crow::connections::systemBus->async_method_call(
2579 [aResp](const boost::system::error_code ec) {
2580 if (ec)
2581 {
2582 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2583 messages::internalError(aResp->res);
2584 return;
2585 }
2586 },
2587 service, path, "org.freedesktop.DBus.Properties", "Set",
2588 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2589 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002590 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002591 }
2592 if (ipsEnterTime)
2593 {
2594 // Convert from seconds into milliseconds for DBus
2595 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2596 crow::connections::systemBus->async_method_call(
2597 [aResp](const boost::system::error_code ec) {
2598 if (ec)
2599 {
2600 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2601 messages::internalError(aResp->res);
2602 return;
2603 }
2604 },
2605 service, path, "org.freedesktop.DBus.Properties", "Set",
2606 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002607 "EnterDwellTime",
2608 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002609 }
2610 if (ipsExitUtil)
2611 {
2612 crow::connections::systemBus->async_method_call(
2613 [aResp](const boost::system::error_code ec) {
2614 if (ec)
2615 {
2616 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2617 messages::internalError(aResp->res);
2618 return;
2619 }
2620 },
2621 service, path, "org.freedesktop.DBus.Properties", "Set",
2622 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2623 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002624 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002625 }
2626 if (ipsExitTime)
2627 {
2628 // Convert from seconds into milliseconds for DBus
2629 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2630 crow::connections::systemBus->async_method_call(
2631 [aResp](const boost::system::error_code ec) {
2632 if (ec)
2633 {
2634 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2635 messages::internalError(aResp->res);
2636 return;
2637 }
2638 },
2639 service, path, "org.freedesktop.DBus.Properties", "Set",
2640 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002641 "ExitDwellTime",
2642 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002643 }
2644 },
2645 "xyz.openbmc_project.ObjectMapper",
2646 "/xyz/openbmc_project/object_mapper",
2647 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2648 std::array<const char*, 1>{
2649 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2650
2651 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2652}
2653
Yong Lic45f0082019-10-10 14:19:01 +08002654/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002655 * SystemsCollection derived class for delivering ComputerSystems Collection
2656 * Schema
2657 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002658inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002659{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002660 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002661 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002662 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002663 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002664 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2665 asyncResp->res.jsonValue["@odata.type"] =
2666 "#ComputerSystemCollection.ComputerSystemCollection";
2667 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2668 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002669
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002670 sdbusplus::asio::getProperty<std::string>(
2671 *crow::connections::systemBus,
2672 "xyz.openbmc_project.Settings",
2673 "/xyz/openbmc_project/network/hypervisor",
2674 "xyz.openbmc_project.Network.SystemConfiguration",
2675 "HostName",
2676 [asyncResp](const boost::system::error_code ec,
2677 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002678 nlohmann::json& ifaceArray =
2679 asyncResp->res.jsonValue["Members"];
2680 ifaceArray = nlohmann::json::array();
2681 auto& count =
2682 asyncResp->res.jsonValue["Members@odata.count"];
2683 ifaceArray.push_back(
2684 {{"@odata.id", "/redfish/v1/Systems/system"}});
2685 count = ifaceArray.size();
2686 if (!ec)
2687 {
2688 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2689 ifaceArray.push_back(
2690 {{"@odata.id",
2691 "/redfish/v1/Systems/hypervisor"}});
2692 count = ifaceArray.size();
2693 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002694 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002695 });
2696}
Sunitha Harish462023a2020-02-19 08:34:59 -06002697
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002698/**
2699 * Function transceives data with dbus directly.
2700 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002701inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002702{
2703 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2704 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2705 constexpr char const* interfaceName =
2706 "xyz.openbmc_project.Control.Host.NMI";
2707 constexpr char const* method = "NMI";
2708
2709 crow::connections::systemBus->async_method_call(
2710 [asyncResp](const boost::system::error_code ec) {
2711 if (ec)
2712 {
2713 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2714 messages::internalError(asyncResp->res);
2715 return;
2716 }
2717 messages::success(asyncResp->res);
2718 },
2719 serviceName, objectPath, interfaceName, method);
2720}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002721
2722/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002723 * SystemActionsReset class supports handle POST method for Reset action.
2724 * The class retrieves and sends data directly to D-Bus.
2725 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002726inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002727{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002728 /**
2729 * Function handles POST method request.
2730 * Analyzes POST body message before sends Reset request data to D-Bus.
2731 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002732 BMCWEB_ROUTE(app,
2733 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002734 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002735 .methods(
2736 boost::beast::http::verb::
2737 post)([](const crow::Request& req,
2738 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2739 std::string resetType;
2740 if (!json_util::readJson(req, asyncResp->res, "ResetType",
2741 resetType))
2742 {
2743 return;
2744 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002745
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002746 // Get the command and host vs. chassis
2747 std::string command;
2748 bool hostCommand;
2749 if ((resetType == "On") || (resetType == "ForceOn"))
2750 {
2751 command = "xyz.openbmc_project.State.Host.Transition.On";
2752 hostCommand = true;
2753 }
2754 else if (resetType == "ForceOff")
2755 {
2756 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2757 hostCommand = false;
2758 }
2759 else if (resetType == "ForceRestart")
2760 {
2761 command =
2762 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2763 hostCommand = true;
2764 }
2765 else if (resetType == "GracefulShutdown")
2766 {
2767 command = "xyz.openbmc_project.State.Host.Transition.Off";
2768 hostCommand = true;
2769 }
2770 else if (resetType == "GracefulRestart")
2771 {
George Liu0fda0f12021-11-16 10:06:17 +08002772 command =
2773 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002774 hostCommand = true;
2775 }
2776 else if (resetType == "PowerCycle")
2777 {
2778 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2779 hostCommand = true;
2780 }
2781 else if (resetType == "Nmi")
2782 {
2783 doNMI(asyncResp);
2784 return;
2785 }
2786 else
2787 {
2788 messages::actionParameterUnknown(asyncResp->res, "Reset",
2789 resetType);
2790 return;
2791 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002792
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002793 if (hostCommand)
2794 {
2795 crow::connections::systemBus->async_method_call(
2796 [asyncResp, resetType](const boost::system::error_code ec) {
2797 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002798 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002799 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2800 if (ec.value() ==
2801 boost::asio::error::invalid_argument)
2802 {
2803 messages::actionParameterNotSupported(
2804 asyncResp->res, resetType, "Reset");
2805 }
2806 else
2807 {
2808 messages::internalError(asyncResp->res);
2809 }
2810 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002811 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002812 messages::success(asyncResp->res);
2813 },
2814 "xyz.openbmc_project.State.Host",
2815 "/xyz/openbmc_project/state/host0",
2816 "org.freedesktop.DBus.Properties", "Set",
2817 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002818 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 }
2820 else
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.Chassis",
2842 "/xyz/openbmc_project/state/chassis0",
2843 "org.freedesktop.DBus.Properties", "Set",
2844 "xyz.openbmc_project.State.Chassis",
2845 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002846 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002847 }
2848 });
2849}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002850
2851/**
Ed Tanous66173382018-08-15 18:20:59 -07002852 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002853 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002854inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002855{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002856
Ed Tanous1abe55e2018-09-05 08:30:59 -07002857 /**
2858 * Functions triggers appropriate requests on DBus
2859 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002860 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002861 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002862 .methods(
2863 boost::beast::http::verb::
2864 get)([](const crow::Request&,
2865 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2866 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002867 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002868 asyncResp->res.jsonValue["Name"] = "system";
2869 asyncResp->res.jsonValue["Id"] = "system";
2870 asyncResp->res.jsonValue["SystemType"] = "Physical";
2871 asyncResp->res.jsonValue["Description"] = "Computer System";
2872 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2873 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2874 "Disabled";
2875 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2876 uint64_t(0);
2877 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2878 "Disabled";
2879 asyncResp->res.jsonValue["@odata.id"] =
2880 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002881
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882 asyncResp->res.jsonValue["Processors"] = {
2883 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2884 asyncResp->res.jsonValue["Memory"] = {
2885 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2886 asyncResp->res.jsonValue["Storage"] = {
2887 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002888
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002889 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2890 {"target",
2891 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2892 {"@Redfish.ActionInfo",
2893 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002894
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002895 asyncResp->res.jsonValue["LogServices"] = {
2896 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002897
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002898 asyncResp->res.jsonValue["Bios"] = {
2899 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002900
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002901 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2902 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002903
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002904 asyncResp->res.jsonValue["Status"] = {
2905 {"Health", "OK"},
2906 {"State", "Enabled"},
2907 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002908
2909 // Fill in SerialConsole info
2910 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2911 15;
2912 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2913 {"ServiceEnabled", true},
2914 };
2915 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2916 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2917 {"ServiceEnabled", true},
2918 {"Port", 2200},
2919 // https://github.com/openbmc/docs/blob/master/console.md
2920 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2921 };
2922
2923#ifdef BMCWEB_ENABLE_KVM
2924 // Fill in GraphicalConsole info
2925 asyncResp->res.jsonValue["GraphicalConsole"] = {
2926 {"ServiceEnabled", true},
2927 {"MaxConcurrentSessions", 4},
2928 {"ConnectTypesSupported", {"KVMIP"}},
2929 };
2930#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002931 constexpr const std::array<const char*, 4> inventoryForSystems = {
2932 "xyz.openbmc_project.Inventory.Item.Dimm",
2933 "xyz.openbmc_project.Inventory.Item.Cpu",
2934 "xyz.openbmc_project.Inventory.Item.Drive",
2935 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002936
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002937 auto health = std::make_shared<HealthPopulate>(asyncResp);
2938 crow::connections::systemBus->async_method_call(
2939 [health](const boost::system::error_code ec,
2940 std::vector<std::string>& resp) {
2941 if (ec)
2942 {
2943 // no inventory
2944 return;
2945 }
2946
2947 health->inventory = std::move(resp);
2948 },
2949 "xyz.openbmc_project.ObjectMapper",
2950 "/xyz/openbmc_project/object_mapper",
2951 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2952 int32_t(0), inventoryForSystems);
2953
2954 health->populate();
2955
2956 getMainChassisId(
2957 asyncResp, [](const std::string& chassisId,
2958 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2959 aRsp->res.jsonValue["Links"]["Chassis"] = {
2960 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2961 });
2962
2963 getLocationIndicatorActive(asyncResp);
2964 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2965 getIndicatorLedState(asyncResp);
2966 getComputerSystem(asyncResp, health);
2967 getHostState(asyncResp);
2968 getBootProperties(asyncResp);
2969 getBootProgress(asyncResp);
2970 getPCIeDeviceList(asyncResp, "PCIeDevices");
2971 getHostWatchdogTimer(asyncResp);
2972 getPowerRestorePolicy(asyncResp);
2973 getAutomaticRetry(asyncResp);
2974 getLastResetTime(asyncResp);
2975#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2976 getProvisioningStatus(asyncResp);
2977#endif
Ali Ahmed19817712021-06-29 17:01:52 -05002978 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05002979 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05002980 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002981 });
2982 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002983 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002984 .methods(boost::beast::http::verb::patch)(
2985 [](const crow::Request& req,
2986 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2987 std::optional<bool> locationIndicatorActive;
2988 std::optional<std::string> indicatorLed;
2989 std::optional<nlohmann::json> bootProps;
2990 std::optional<nlohmann::json> wdtTimerProps;
2991 std::optional<std::string> assetTag;
2992 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05002993 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05002994 std::optional<nlohmann::json> ipsProps;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002995 if (!json_util::readJson(
2996 req, asyncResp->res, "IndicatorLED", indicatorLed,
2997 "LocationIndicatorActive", locationIndicatorActive,
2998 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
2999 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003000 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3001 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003002 {
James Feistb49ac872019-05-21 15:12:01 -07003003 return;
3004 }
3005
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003006 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003007
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003008 if (assetTag)
3009 {
3010 setAssetTag(asyncResp, *assetTag);
3011 }
James Feistb49ac872019-05-21 15:12:01 -07003012
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003013 if (wdtTimerProps)
3014 {
3015 std::optional<bool> wdtEnable;
3016 std::optional<std::string> wdtTimeOutAction;
3017
3018 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3019 "FunctionEnabled", wdtEnable,
3020 "TimeoutAction", wdtTimeOutAction))
3021 {
3022 return;
3023 }
3024 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3025 }
3026
3027 if (bootProps)
3028 {
3029 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003030 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003031 std::optional<std::string> bootEnable;
3032 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003033 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003034
3035 if (!json_util::readJson(
3036 *bootProps, asyncResp->res,
3037 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003038 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003040 "AutomaticRetryConfig", automaticRetryConfig,
3041 "TrustedModuleRequiredToBoot",
3042 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003043 {
3044 return;
3045 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003046
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003047 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003048 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003049 setBootProperties(asyncResp, bootSource, bootType,
3050 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003051 }
3052 if (automaticRetryConfig)
3053 {
3054 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3055 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003056
3057 if (trustedModuleRequiredToBoot)
3058 {
3059 setTrustedModuleRequiredToBoot(
3060 asyncResp, *trustedModuleRequiredToBoot);
3061 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003062 }
3063
3064 if (locationIndicatorActive)
3065 {
3066 setLocationIndicatorActive(asyncResp,
3067 *locationIndicatorActive);
3068 }
3069
3070 // TODO (Gunnar): Remove IndicatorLED after enough time has
3071 // passed
3072 if (indicatorLed)
3073 {
3074 setIndicatorLedState(asyncResp, *indicatorLed);
3075 asyncResp->res.addHeader(
3076 boost::beast::http::field::warning,
3077 "299 - \"IndicatorLED is deprecated. Use "
3078 "LocationIndicatorActive instead.\"");
3079 }
3080
3081 if (powerRestorePolicy)
3082 {
3083 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3084 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003085
3086 if (powerMode)
3087 {
3088 setPowerMode(asyncResp, *powerMode);
3089 }
Chris Cain37bbf982021-09-20 10:53:09 -05003090
3091 if (ipsProps)
3092 {
3093 std::optional<bool> ipsEnable;
3094 std::optional<uint8_t> ipsEnterUtil;
3095 std::optional<uint64_t> ipsEnterTime;
3096 std::optional<uint8_t> ipsExitUtil;
3097 std::optional<uint64_t> ipsExitTime;
3098
3099 if (!json_util::readJson(
3100 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3101 "EnterUtilizationPercent", ipsEnterUtil,
3102 "EnterDwellTimeSeconds", ipsEnterTime,
3103 "ExitUtilizationPercent", ipsExitUtil,
3104 "ExitDwellTimeSeconds", ipsExitTime))
3105 {
3106 return;
3107 }
3108 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3109 ipsEnterTime, ipsExitUtil, ipsExitTime);
3110 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003111 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003112}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303113
3114/**
3115 * SystemResetActionInfo derived class for delivering Computer Systems
3116 * ResetType AllowableValues using ResetInfo schema.
3117 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003118inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303119{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303120
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303121 /**
3122 * Functions triggers appropriate requests on DBus
3123 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003124 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003125 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003126 .methods(boost::beast::http::verb::get)(
3127 [](const crow::Request&,
3128 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3129 asyncResp->res.jsonValue = {
3130 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3131 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3132 {"Name", "Reset Action Info"},
3133 {"Id", "ResetActionInfo"},
3134 {"Parameters",
3135 {{{"Name", "ResetType"},
3136 {"Required", true},
3137 {"DataType", "String"},
3138 {"AllowableValues",
3139 {"On", "ForceOff", "ForceOn", "ForceRestart",
3140 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3141 "Nmi"}}}}}};
3142 });
3143}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003144} // namespace redfish