blob: ec4db212269afd896e2ab20966b2a1598203ca4a [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
23
John Edward Broadbent7e860f12021-04-08 15:57:16 -070024#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070025#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080026#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070027#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070028#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060029#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050031
Ed Tanousabf2add2019-01-22 16:40:12 -080032#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034namespace redfish
35{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020036
Alpana Kumari9d3ae102019-04-12 06:49:32 -050037/**
38 * @brief Updates the Functional State of DIMMs
39 *
40 * @param[in] aResp Shared pointer for completing asynchronous calls
41 * @param[in] dimmState Dimm's Functional state, true/false
42 *
43 * @return None.
44 */
zhanghch058d1b46d2021-04-01 11:18:24 +080045inline void
46 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070047 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070049 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050
Gunnar Mills4e0453b2020-07-08 14:00:30 -050051 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052 // Update STATE only if previous State was DISABLED and current Dimm is
53 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050054 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050055 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
56 if (prevMemSummary == "Disabled")
57 {
Ed Tanouse05aec52022-01-25 10:28:56 -080058 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059 {
60 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
61 "Enabled";
62 }
63 }
64}
65
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050066/*
67 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
68 *
69 * @param[in] aResp Shared pointer for completing asynchronous calls
70 * @param[in] cpuPresenceState CPU present or not
71 *
72 * @return None.
73 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074inline void
75 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
76 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070078 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079
Ed Tanous55f79e62022-01-25 11:26:16 -080080 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050082 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080083 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080084 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050085 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080086 if (procCountPtr != nullptr)
87 {
88 // shouldn't be possible to be nullptr
89 *procCountPtr += 1;
90 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050091 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092}
93
94/*
95 * @brief Update "ProcessorSummary" "Status" "State" based on
96 * CPU Functional State
97 *
98 * @param[in] aResp Shared pointer for completing asynchronous calls
99 * @param[in] cpuFunctionalState is CPU functional true/false
100 *
101 * @return None.
102 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700103inline void
104 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
105 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500106{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700107 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500108
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500109 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500110 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
111
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500112 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113 // Update STATE only if previous State was Non_Functional and current CPU is
114 // Functional.
115 if (prevProcState == "Disabled")
116 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800117 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500118 {
119 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
120 "Enabled";
121 }
122 }
123}
124
Ali Ahmed03fbed92021-09-03 02:33:43 -0500125inline void getProcessorProperties(
126 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
127 const std::string& path,
Ed Tanous168e20c2021-12-13 14:39:53 -0800128 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
Ali Ahmed03fbed92021-09-03 02:33:43 -0500129 properties)
130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
Ed Tanouse662eae2022-01-25 10:39:19 -0800179 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500180 {
181 messages::internalError(aResp->res);
182 return;
183 }
184
185 nlohmann::json& coreCount =
186 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
187 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
188
189 if (coreCountPtr == nullptr)
190 {
191 coreCount = 0;
192 }
193 else
194 {
195 *coreCountPtr += *coreCountVal;
196 }
197 }
198 }
199}
200
201/*
202 * @brief Get ProcessorSummary fields
203 *
204 * @param[in] aResp Shared pointer for completing asynchronous calls
205 * @param[in] service dbus service for Cpu Information
206 * @param[in] path dbus path for Cpu
207 *
208 * @return None.
209 */
210inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 const std::string& service,
212 const std::string& path)
213{
214
215 crow::connections::systemBus->async_method_call(
216 [aResp, service,
217 path](const boost::system::error_code ec2,
218 const std::vector<std::pair<
Ed Tanous168e20c2021-12-13 14:39:53 -0800219 std::string, dbus::utility::DbusVariantType>>& properties) {
Ali Ahmed03fbed92021-09-03 02:33:43 -0500220 if (ec2)
221 {
222 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
223 messages::internalError(aResp->res);
224 return;
225 }
226 getProcessorProperties(aResp, service, path, properties);
227 },
228 service, path, "org.freedesktop.DBus.Properties", "GetAll",
229 "xyz.openbmc_project.Inventory.Item.Cpu");
230}
231
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500232/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700233 * @brief Retrieves computer system properties over dbus
234 *
235 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500236 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700237 *
238 * @return None.
239 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700240inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800241 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700242 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700243{
Ed Tanous6c34de42018-08-29 13:37:36 -0700244 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500245
Ed Tanous6c34de42018-08-29 13:37:36 -0700246 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700247 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700248 const boost::system::error_code ec,
249 const std::vector<std::pair<
250 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500251 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
252 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700253 if (ec)
254 {
255 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700256 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700257 return;
258 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700259 // Iterate over all retrieved ObjectPaths.
260 for (const std::pair<std::string,
261 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500262 std::string, std::vector<std::string>>>>&
263 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700264 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500265 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 BMCWEB_LOG_DEBUG << "Got path: " << path;
267 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500268 std::pair<std::string, std::vector<std::string>>>&
269 connectionNames = object.second;
Ed Tanous26f69762022-01-25 09:49:11 -0800270 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700271 {
272 continue;
273 }
Ed Tanous029573d2019-02-01 10:57:49 -0800274
James Feist5bc2dc82019-10-22 14:33:16 -0700275 auto memoryHealth = std::make_shared<HealthPopulate>(
276 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
277
278 auto cpuHealth = std::make_shared<HealthPopulate>(
279 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
280
281 systemHealth->children.emplace_back(memoryHealth);
282 systemHealth->children.emplace_back(cpuHealth);
283
Ed Tanous029573d2019-02-01 10:57:49 -0800284 // This is not system, so check if it's cpu, dimm, UUID or
285 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500286 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700287 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500288 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700289 {
Ed Tanous029573d2019-02-01 10:57:49 -0800290 if (interfaceName ==
291 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700292 {
Ed Tanous029573d2019-02-01 10:57:49 -0800293 BMCWEB_LOG_DEBUG
294 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500295
Ed Tanous029573d2019-02-01 10:57:49 -0800296 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500297 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700298 path](const boost::system::error_code ec2,
Ed Tanous168e20c2021-12-13 14:39:53 -0800299 const std::vector<std::pair<
300 std::string,
301 dbus::utility::DbusVariantType>>&
Ed Tanousf23b7292020-10-15 09:41:17 -0700302 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000303 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800304 {
305 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000306 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800307 messages::internalError(aResp->res);
308 return;
309 }
310 BMCWEB_LOG_DEBUG << "Got "
311 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500312 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500313
Ed Tanous26f69762022-01-25 09:49:11 -0800314 if (!properties.empty())
Ed Tanous029573d2019-02-01 10:57:49 -0800315 {
Ed Tanous168e20c2021-12-13 14:39:53 -0800316 for (const std::pair<
317 std::string,
318 dbus::utility::
319 DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700321 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800322 if (property.first !=
323 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700324 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800325 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700326 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500327 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500328 std::get_if<uint32_t>(
329 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800330 if (value == nullptr)
331 {
332 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800333 << "Find incorrect type of MemorySize";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800334 continue;
335 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500336 nlohmann::json& totalMemory =
George Liu0fda0f12021-11-16 10:06:17 +0800337 aResp->res.jsonValue
338 ["MemorySummary"]
339 ["TotalSystemMemoryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500340 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800341 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500342 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800343 if (preValue == nullptr)
344 {
345 continue;
346 }
George Liu0fda0f12021-11-16 10:06:17 +0800347 aResp->res.jsonValue
348 ["MemorySummary"]
349 ["TotalSystemMemoryGiB"] =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800350 *value / (1024 * 1024) +
351 *preValue;
352 aResp->res
353 .jsonValue["MemorySummary"]
354 ["Status"]["State"] =
355 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700356 }
Ed Tanous029573d2019-02-01 10:57:49 -0800357 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500358 else
359 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700360 sdbusplus::asio::getProperty<bool>(
361 *crow::connections::systemBus,
362 service, path,
363 "xyz.openbmc_project.State."
364 "Decorator.OperationalStatus",
365 "Functional",
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500366 [aResp](
367 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000368 ec3,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700369 bool dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000370 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500371 {
372 BMCWEB_LOG_ERROR
George Liu0fda0f12021-11-16 10:06:17 +0800373 << "DBUS response error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000374 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500375 return;
376 }
377 updateDimmProperties(aResp,
378 dimmState);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700379 });
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500380 }
Ed Tanous029573d2019-02-01 10:57:49 -0800381 },
382 connection.first, path,
383 "org.freedesktop.DBus.Properties", "GetAll",
384 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700385
386 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800387 }
388 else if (interfaceName ==
389 "xyz.openbmc_project.Inventory.Item.Cpu")
390 {
391 BMCWEB_LOG_DEBUG
392 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500393
Ali Ahmed03fbed92021-09-03 02:33:43 -0500394 getProcessorSummary(aResp, connection.first, path);
James Feist5bc2dc82019-10-22 14:33:16 -0700395
396 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800397 }
398 else if (interfaceName ==
399 "xyz.openbmc_project.Common.UUID")
400 {
401 BMCWEB_LOG_DEBUG
402 << "Found UUID, now get its properties.";
403 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800404 [aResp](const boost::system::error_code ec3,
405 const std::vector<std::pair<
406 std::string,
407 dbus::utility::DbusVariantType>>&
408 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000409 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800410 {
411 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000412 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800413 messages::internalError(aResp->res);
414 return;
415 }
416 BMCWEB_LOG_DEBUG << "Got "
417 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500418 << " UUID properties.";
Ed Tanous168e20c2021-12-13 14:39:53 -0800419 for (const std::pair<
420 std::string,
421 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500422 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800423 {
Ed Tanous029573d2019-02-01 10:57:49 -0800424 if (property.first == "UUID")
425 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500426 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500427 std::get_if<std::string>(
428 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700429
Ed Tanous029573d2019-02-01 10:57:49 -0800430 if (value != nullptr)
431 {
432 std::string valueStr = *value;
433 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700434 {
Ed Tanous029573d2019-02-01 10:57:49 -0800435 valueStr.insert(8, 1, '-');
436 valueStr.insert(13, 1, '-');
437 valueStr.insert(18, 1, '-');
438 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700439 }
Ed Tanous029573d2019-02-01 10:57:49 -0800440 BMCWEB_LOG_DEBUG << "UUID = "
441 << valueStr;
442 aResp->res.jsonValue["UUID"] =
443 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700444 }
445 }
Ed Tanous029573d2019-02-01 10:57:49 -0800446 }
447 },
448 connection.first, path,
449 "org.freedesktop.DBus.Properties", "GetAll",
450 "xyz.openbmc_project.Common.UUID");
451 }
452 else if (interfaceName ==
453 "xyz.openbmc_project.Inventory.Item.System")
454 {
455 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800456 [aResp](const boost::system::error_code ec2,
457 const std::vector<std::pair<
458 std::string,
459 dbus::utility::DbusVariantType>>&
460 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000461 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800462 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700463 // doesn't have to include this
464 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800465 return;
466 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500467 BMCWEB_LOG_DEBUG
468 << "Got " << propertiesList.size()
469 << " properties for system";
Ed Tanous168e20c2021-12-13 14:39:53 -0800470 for (const std::pair<
471 std::string,
472 dbus::utility::DbusVariantType>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500473 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800474 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500475 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600476 property.first;
477 if ((propertyName == "PartNumber") ||
478 (propertyName == "SerialNumber") ||
479 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500480 (propertyName == "Model") ||
481 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800482 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500483 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600484 std::get_if<std::string>(
485 &property.second);
486 if (value != nullptr)
487 {
488 aResp->res
489 .jsonValue[propertyName] =
490 *value;
491 }
Ed Tanous029573d2019-02-01 10:57:49 -0800492 }
493 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500494
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600495 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500496 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600497 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500498 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800499 },
500 connection.first, path,
501 "org.freedesktop.DBus.Properties", "GetAll",
George Liu0fda0f12021-11-16 10:06:17 +0800502 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700503
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700504 sdbusplus::asio::getProperty<std::string>(
505 *crow::connections::systemBus, connection.first,
506 path,
507 "xyz.openbmc_project.Inventory.Decorator."
508 "AssetTag",
509 "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -0800510 [aResp](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700511 const std::string& value) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000512 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700513 {
514 // doesn't have to include this
515 // interface
516 return;
517 }
518
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700519 aResp->res.jsonValue["AssetTag"] = value;
520 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700521 }
522 }
523 }
524 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700525 },
526 "xyz.openbmc_project.ObjectMapper",
527 "/xyz/openbmc_project/object_mapper",
528 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700529 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500530 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700531 "xyz.openbmc_project.Inventory.Decorator.Asset",
532 "xyz.openbmc_project.Inventory.Item.Cpu",
533 "xyz.openbmc_project.Inventory.Item.Dimm",
534 "xyz.openbmc_project.Inventory.Item.System",
535 "xyz.openbmc_project.Common.UUID",
536 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700537}
538
539/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 * @brief Retrieves host state properties over dbus
541 *
542 * @param[in] aResp Shared pointer for completing asynchronous calls.
543 *
544 * @return None.
545 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800546inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700547{
548 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700549 sdbusplus::asio::getProperty<std::string>(
550 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
551 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
552 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800553 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700554 const std::string& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700555 if (ec)
556 {
Andrew Geissler22228c22022-01-31 13:55:33 -0600557 if (ec == boost::system::errc::host_unreachable)
558 {
559 // Service not available, no error, just don't return
560 // host state info
561 BMCWEB_LOG_DEBUG << "Service not available " << ec;
562 return;
563 }
564 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700565 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 return;
567 }
Ed Tanous66173382018-08-15 18:20:59 -0700568
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700569 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
570 // Verify Host State
571 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700572 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700573 aResp->res.jsonValue["PowerState"] = "On";
574 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700575 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700576 else if (hostState ==
577 "xyz.openbmc_project.State.Host.HostState.Quiesced")
578 {
579 aResp->res.jsonValue["PowerState"] = "On";
580 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
581 }
582 else if (hostState ==
583 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
584 {
585 aResp->res.jsonValue["PowerState"] = "On";
586 aResp->res.jsonValue["Status"]["State"] = "InTest";
587 }
588 else if (
589 hostState ==
590 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
591 {
592 aResp->res.jsonValue["PowerState"] = "PoweringOn";
593 aResp->res.jsonValue["Status"]["State"] = "Starting";
594 }
595 else if (
596 hostState ==
597 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
598 {
599 aResp->res.jsonValue["PowerState"] = "PoweringOff";
600 aResp->res.jsonValue["Status"]["State"] = "Disabled";
601 }
602 else
603 {
604 aResp->res.jsonValue["PowerState"] = "Off";
605 aResp->res.jsonValue["Status"]["State"] = "Disabled";
606 }
607 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700608}
609
610/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500611 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530612 *
613 * @param[in] dbusSource The boot source in DBUS speak.
614 *
615 * @return Returns as a string, the boot source in Redfish terms. If translation
616 * cannot be done, returns an empty string.
617 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000618inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530619{
620 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
621 {
622 return "None";
623 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700624 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530625 {
626 return "Hdd";
627 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700628 if (dbusSource ==
629 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530630 {
631 return "Cd";
632 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700633 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530634 {
635 return "Pxe";
636 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700637 if (dbusSource ==
638 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700639 {
640 return "Usb";
641 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700642 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530643}
644
645/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300646 * @brief Translates boot type DBUS property value to redfish.
647 *
648 * @param[in] dbusType The boot type in DBUS speak.
649 *
650 * @return Returns as a string, the boot type in Redfish terms. If translation
651 * cannot be done, returns an empty string.
652 */
653inline std::string dbusToRfBootType(const std::string& dbusType)
654{
655 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
656 {
657 return "Legacy";
658 }
659 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
660 {
661 return "UEFI";
662 }
663 return "";
664}
665
666/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500667 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668 *
669 * @param[in] dbusMode The boot mode in DBUS speak.
670 *
671 * @return Returns as a string, the boot mode in Redfish terms. If translation
672 * cannot be done, returns an empty string.
673 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000674inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530675{
676 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
677 {
678 return "None";
679 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700680 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530681 {
682 return "Diags";
683 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700684 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530685 {
686 return "BiosSetup";
687 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700688 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530689}
690
691/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600692 * @brief Translates boot progress DBUS property value to redfish.
693 *
694 * @param[in] dbusBootProgress The boot progress in DBUS speak.
695 *
696 * @return Returns as a string, the boot progress in Redfish terms. If
697 * translation cannot be done, returns "None".
698 */
699inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
700{
701 // Now convert the D-Bus BootProgress to the appropriate Redfish
702 // enum
703 std::string rfBpLastState = "None";
704 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
705 "ProgressStages.Unspecified")
706 {
707 rfBpLastState = "None";
708 }
709 else if (dbusBootProgress ==
710 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
711 "PrimaryProcInit")
712 {
713 rfBpLastState = "PrimaryProcessorInitializationStarted";
714 }
715 else if (dbusBootProgress ==
716 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
717 "BusInit")
718 {
719 rfBpLastState = "BusInitializationStarted";
720 }
721 else if (dbusBootProgress ==
722 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
723 "MemoryInit")
724 {
725 rfBpLastState = "MemoryInitializationStarted";
726 }
727 else if (dbusBootProgress ==
728 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
729 "SecondaryProcInit")
730 {
731 rfBpLastState = "SecondaryProcessorInitializationStarted";
732 }
733 else if (dbusBootProgress ==
734 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
735 "PCIInit")
736 {
737 rfBpLastState = "PCIResourceConfigStarted";
738 }
739 else if (dbusBootProgress ==
740 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
741 "SystemSetup")
742 {
743 rfBpLastState = "SetupEntered";
744 }
745 else if (dbusBootProgress ==
746 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
747 "SystemInitComplete")
748 {
749 rfBpLastState = "SystemHardwareInitializationComplete";
750 }
751 else if (dbusBootProgress ==
752 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
753 "OSStart")
754 {
755 rfBpLastState = "OSBootStarted";
756 }
757 else if (dbusBootProgress ==
758 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
759 "OSRunning")
760 {
761 rfBpLastState = "OSRunning";
762 }
763 else
764 {
765 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
766 << dbusBootProgress;
767 // Just return the default
768 }
769 return rfBpLastState;
770}
771
772/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500773 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530774 *
775 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700776 * @param[out] bootSource The DBus source
777 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530778 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800781inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500782 const std::string& rfSource,
783 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300785 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
786 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530788 if (rfSource == "None")
789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700792 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530793 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
795 }
796 else if (rfSource == "Hdd")
797 {
798 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
799 }
800 else if (rfSource == "Diags")
801 {
802 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
803 }
804 else if (rfSource == "Cd")
805 {
806 bootSource =
807 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
808 }
809 else if (rfSource == "BiosSetup")
810 {
811 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530812 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 else if (rfSource == "Usb")
814 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700815 bootSource =
816 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700817 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530818 else
819 {
George Liu0fda0f12021-11-16 10:06:17 +0800820 BMCWEB_LOG_DEBUG
821 << "Invalid property value for BootSourceOverrideTarget: "
822 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 messages::propertyValueNotInList(aResp->res, rfSource,
824 "BootSourceTargetOverride");
825 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530826 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700827 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828}
Ali Ahmed19817712021-06-29 17:01:52 -0500829
Andrew Geissler978b8802020-11-19 13:36:40 -0600830/**
831 * @brief Retrieves boot progress of the system
832 *
833 * @param[in] aResp Shared pointer for generating response message.
834 *
835 * @return None.
836 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800837inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600838{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700839 sdbusplus::asio::getProperty<std::string>(
840 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
841 "/xyz/openbmc_project/state/host0",
842 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600843 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700844 const std::string& bootProgressStr) {
Andrew Geissler978b8802020-11-19 13:36:40 -0600845 if (ec)
846 {
847 // BootProgress is an optional object so just do nothing if
848 // not found
849 return;
850 }
851
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700852 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600853
Andrew Geisslere43914b2022-01-06 13:59:39 -0600854 aResp->res.jsonValue["BootProgress"]["LastState"] =
855 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700856 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600857}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530858
859/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300860 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300861 *
862 * @param[in] aResp Shared pointer for generating response message.
863 *
864 * @return None.
865 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300867inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700869 sdbusplus::asio::getProperty<std::string>(
870 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
871 "/xyz/openbmc_project/control/host0/boot",
872 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300873 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700874 const std::string& bootType) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300875 if (ec)
876 {
877 // not an error, don't have to have the interface
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300878 return;
879 }
880
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700881 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882
George Liu0fda0f12021-11-16 10:06:17 +0800883 aResp->res
884 .jsonValue["Boot"]
885 ["BootSourceOverrideMode@Redfish.AllowableValues"] = {
886 "Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300887
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700888 auto rfType = dbusToRfBootType(bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300889 if (rfType.empty())
890 {
891 messages::internalError(aResp->res);
892 return;
893 }
894
895 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700896 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300897}
898
899/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300900 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530901 *
902 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530903 *
904 * @return None.
905 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300906
907inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700909 sdbusplus::asio::getProperty<std::string>(
910 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
911 "/xyz/openbmc_project/control/host0/boot",
912 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300913 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700914 const std::string& bootModeStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 if (ec)
916 {
917 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
918 messages::internalError(aResp->res);
919 return;
920 }
921
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700922 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923
George Liu0fda0f12021-11-16 10:06:17 +0800924 aResp->res
925 .jsonValue["Boot"]
926 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
927 {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530928
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700929 if (bootModeStr !=
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530930 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
931 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700932 auto rfMode = dbusToRfBootMode(bootModeStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530933 if (!rfMode.empty())
934 {
935 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
936 rfMode;
937 }
938 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700939 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940}
941
942/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
945 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530946 *
947 * @return None.
948 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300949
950inline void
951 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530952{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700953 sdbusplus::asio::getProperty<std::string>(
954 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
955 "/xyz/openbmc_project/control/host0/boot",
956 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300957 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700958 const std::string& bootSourceStr) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 if (ec)
960 {
961 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
962 messages::internalError(aResp->res);
963 return;
964 }
965
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700966 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530967
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700968 auto rfSource = dbusToRfBootSource(bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530969 if (!rfSource.empty())
970 {
971 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
972 rfSource;
973 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300974
975 // Get BootMode as BootSourceOverrideTarget is constructed
976 // from both BootSource and BootMode
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300977 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700978 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530979}
980
981/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300982 * @brief This functions abstracts all the logic behind getting a
983 * "BootSourceOverrideEnabled" property from an overall boot override enable
984 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985 *
986 * @param[in] aResp Shared pointer for generating response message.
987 *
988 * @return None.
989 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300991inline void
992 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
993 const bool bootOverrideEnableSetting)
994{
995 if (!bootOverrideEnableSetting)
996 {
997 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
998 return;
999 }
1000
1001 // If boot source override is enabled, we need to check 'one_time'
1002 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001003 sdbusplus::asio::getProperty<bool>(
1004 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1005 "/xyz/openbmc_project/control/host0/boot/one_time",
1006 "xyz.openbmc_project.Object.Enable", "Enabled",
1007 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008 if (ec)
1009 {
1010 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001011 messages::internalError(aResp->res);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301012 return;
1013 }
1014
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001015 if (oneTimeSetting)
1016 {
1017 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1018 "Once";
1019 }
1020 else
1021 {
1022 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1023 "Continuous";
1024 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001025 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026}
1027
1028/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001029 * @brief Retrieves boot override enable over DBUS
1030 *
1031 * @param[in] aResp Shared pointer for generating response message.
1032 *
1033 * @return None.
1034 */
1035
1036inline void
1037 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1038{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001039 sdbusplus::asio::getProperty<bool>(
1040 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1041 "/xyz/openbmc_project/control/host0/boot",
1042 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001044 const bool bootOverrideEnable) {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001045 if (ec)
1046 {
1047 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1048 messages::internalError(aResp->res);
1049 return;
1050 }
1051
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001052 processBootOverrideEnable(aResp, bootOverrideEnable);
1053 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001054}
1055
1056/**
1057 * @brief Retrieves boot source override properties
1058 *
1059 * @param[in] aResp Shared pointer for generating response message.
1060 *
1061 * @return None.
1062 */
1063inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1064{
1065 BMCWEB_LOG_DEBUG << "Get boot information.";
1066
1067 getBootOverrideSource(aResp);
1068 getBootOverrideType(aResp);
1069 getBootOverrideEnable(aResp);
1070}
1071
1072/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001073 * @brief Retrieves the Last Reset Time
1074 *
1075 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1076 * and power off. Even though this is the "system" Redfish object look at the
1077 * chassis D-Bus interface for the LastStateChangeTime since this has the
1078 * last power operation time.
1079 *
1080 * @param[in] aResp Shared pointer for generating response message.
1081 *
1082 * @return None.
1083 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001084inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001085{
1086 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1087
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001088 sdbusplus::asio::getProperty<uint64_t>(
1089 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1090 "/xyz/openbmc_project/state/chassis0",
1091 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1092 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001093 if (ec)
1094 {
1095 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1096 return;
1097 }
1098
Gunnar Millsc0557e12020-06-30 11:26:20 -05001099 // LastStateChangeTime is epoch time, in milliseconds
1100 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001101 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001102
1103 // Convert to ISO 8601 standard
1104 aResp->res.jsonValue["LastResetTime"] =
Nan Zhou1d8782e2021-11-29 22:23:18 -08001105 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001106 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001107}
1108
1109/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001110 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1111 *
1112 * @param[in] aResp Shared pointer for generating response message.
1113 *
1114 * @return None.
1115 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001116inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001117{
1118 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1119
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001120 sdbusplus::asio::getProperty<bool>(
1121 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1122 "/xyz/openbmc_project/control/host0/auto_reboot",
1123 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1124 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001125 if (ec)
1126 {
1127 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1128 return;
1129 }
1130
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001131 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
Ed Tanouse05aec52022-01-25 10:28:56 -08001132 if (autoRebootEnabled)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001133 {
1134 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1135 "RetryAttempts";
1136 // If AutomaticRetry (AutoReboot) is enabled see how many
1137 // attempts are left
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001138 sdbusplus::asio::getProperty<uint32_t>(
1139 *crow::connections::systemBus,
1140 "xyz.openbmc_project.State.Host",
1141 "/xyz/openbmc_project/state/host0",
1142 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1143 "AttemptsLeft",
Ed Tanouscb13a392020-07-25 19:02:03 +00001144 [aResp](const boost::system::error_code ec2,
Ed Tanous914e2d52022-01-07 11:38:34 -08001145 const uint32_t autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001146 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001147 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001148 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001149 return;
1150 }
1151
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001152 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001153 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001154
1155 aResp->res
1156 .jsonValue["Boot"]
1157 ["RemainingAutomaticRetryAttempts"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001158 autoRebootAttemptsLeft;
1159 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001160 }
1161 else
1162 {
1163 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1164 "Disabled";
1165 }
1166
1167 // Not on D-Bus. Hardcoded here:
1168 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1169 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001170
1171 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1172 // and RetryAttempts. OpenBMC only supports Disabled and
1173 // RetryAttempts.
George Liu0fda0f12021-11-16 10:06:17 +08001174 aResp->res
1175 .jsonValue["Boot"]
1176 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1177 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001178 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001179}
1180
1181/**
George Liuc6a620f2020-04-10 17:18:11 +08001182 * @brief Retrieves power restore policy over DBUS.
1183 *
1184 * @param[in] aResp Shared pointer for generating response message.
1185 *
1186 * @return None.
1187 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001188inline void
1189 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001190{
1191 BMCWEB_LOG_DEBUG << "Get power restore policy";
1192
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001193 sdbusplus::asio::getProperty<std::string>(
1194 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1195 "/xyz/openbmc_project/control/host0/power_restore_policy",
1196 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1197 [aResp](const boost::system::error_code ec, const std::string& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001198 if (ec)
1199 {
1200 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1201 return;
1202 }
1203
George Liu0fda0f12021-11-16 10:06:17 +08001204 const boost::container::flat_map<std::string, std::string> policyMaps = {
1205 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1206 "AlwaysOn"},
1207 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1208 "AlwaysOff"},
1209 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1210 "LastState"}};
George Liuc6a620f2020-04-10 17:18:11 +08001211
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001212 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001213 if (policyMapsIt == policyMaps.end())
1214 {
1215 messages::internalError(aResp->res);
1216 return;
1217 }
1218
1219 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001220 });
George Liuc6a620f2020-04-10 17:18:11 +08001221}
1222
1223/**
Ali Ahmed19817712021-06-29 17:01:52 -05001224 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1225 * TPM is required for booting the host.
1226 *
1227 * @param[in] aResp Shared pointer for generating response message.
1228 *
1229 * @return None.
1230 */
1231inline void getTrustedModuleRequiredToBoot(
1232 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1233{
1234 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1235
1236 crow::connections::systemBus->async_method_call(
1237 [aResp](
1238 const boost::system::error_code ec,
1239 std::vector<std::pair<
1240 std::string,
1241 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1242 subtree) {
1243 if (ec)
1244 {
1245 BMCWEB_LOG_DEBUG
1246 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1247 // This is an optional D-Bus object so just return if
1248 // error occurs
1249 return;
1250 }
Ed Tanous26f69762022-01-25 09:49:11 -08001251 if (subtree.empty())
Ali Ahmed19817712021-06-29 17:01:52 -05001252 {
1253 // As noted above, this is an optional interface so just return
1254 // if there is no instance found
1255 return;
1256 }
1257
1258 /* When there is more than one TPMEnable object... */
1259 if (subtree.size() > 1)
1260 {
1261 BMCWEB_LOG_DEBUG
1262 << "DBUS response has more than 1 TPM Enable object:"
1263 << subtree.size();
1264 // Throw an internal Error and return
1265 messages::internalError(aResp->res);
1266 return;
1267 }
1268
1269 // Make sure the Dbus response map has a service and objectPath
1270 // field
1271 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1272 {
1273 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1274 messages::internalError(aResp->res);
1275 return;
1276 }
1277
1278 const std::string& path = subtree[0].first;
1279 const std::string& serv = subtree[0].second.begin()->first;
1280
1281 // Valid TPM Enable object found, now reading the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001282 sdbusplus::asio::getProperty<bool>(
1283 *crow::connections::systemBus, serv, path,
1284 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1285 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001286 if (ec)
1287 {
1288 BMCWEB_LOG_DEBUG
1289 << "D-BUS response error on TPM.Policy Get" << ec;
1290 messages::internalError(aResp->res);
1291 return;
1292 }
1293
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001294 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001295 {
1296 aResp->res
1297 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1298 "Required";
1299 }
1300 else
1301 {
1302 aResp->res
1303 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1304 "Disabled";
1305 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001306 });
Ali Ahmed19817712021-06-29 17:01:52 -05001307 },
1308 "xyz.openbmc_project.ObjectMapper",
1309 "/xyz/openbmc_project/object_mapper",
1310 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1311 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1312}
1313
1314/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001315 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1316 * TPM is required for booting the host.
1317 *
1318 * @param[in] aResp Shared pointer for generating response message.
1319 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1320 *
1321 * @return None.
1322 */
1323inline void setTrustedModuleRequiredToBoot(
1324 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1325{
1326 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1327
1328 crow::connections::systemBus->async_method_call(
1329 [aResp, tpmRequired](
1330 const boost::system::error_code ec,
1331 std::vector<std::pair<
1332 std::string,
1333 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1334 subtree) {
1335 if (ec)
1336 {
1337 BMCWEB_LOG_DEBUG
1338 << "DBUS response error on TPM.Policy GetSubTree" << ec;
1339 messages::internalError(aResp->res);
1340 return;
1341 }
Ed Tanous26f69762022-01-25 09:49:11 -08001342 if (subtree.empty())
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001343 {
1344 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1345 "TrustedModuleRequiredToBoot");
1346 return;
1347 }
1348
1349 /* When there is more than one TPMEnable object... */
1350 if (subtree.size() > 1)
1351 {
1352 BMCWEB_LOG_DEBUG
1353 << "DBUS response has more than 1 TPM Enable object:"
1354 << subtree.size();
1355 // Throw an internal Error and return
1356 messages::internalError(aResp->res);
1357 return;
1358 }
1359
1360 // Make sure the Dbus response map has a service and objectPath
1361 // field
1362 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1363 {
1364 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1365 messages::internalError(aResp->res);
1366 return;
1367 }
1368
1369 const std::string& path = subtree[0].first;
1370 const std::string& serv = subtree[0].second.begin()->first;
1371
1372 if (serv.empty())
1373 {
1374 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1375 messages::internalError(aResp->res);
1376 return;
1377 }
1378
1379 // Valid TPM Enable object found, now setting the value
1380 crow::connections::systemBus->async_method_call(
1381 [aResp](const boost::system::error_code ec) {
1382 if (ec)
1383 {
George Liu0fda0f12021-11-16 10:06:17 +08001384 BMCWEB_LOG_DEBUG
1385 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1386 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001387 messages::internalError(aResp->res);
1388 return;
1389 }
1390 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1391 },
1392 serv, path, "org.freedesktop.DBus.Properties", "Set",
1393 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous168e20c2021-12-13 14:39:53 -08001394 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001395 },
1396 "xyz.openbmc_project.ObjectMapper",
1397 "/xyz/openbmc_project/object_mapper",
1398 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1399 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1400}
1401
1402/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301403 * @brief Sets boot properties into DBUS object(s).
1404 *
1405 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001406 * @param[in] bootType The boot type to set.
1407 * @return Integer error code.
1408 */
1409inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001410 const std::optional<std::string>& bootType)
1411{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001412 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001413
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001414 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001415 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001416 return;
1417 }
1418
1419 // Source target specified
1420 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1421 // Figure out which DBUS interface and property to use
1422 if (*bootType == "Legacy")
1423 {
1424 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1425 }
1426 else if (*bootType == "UEFI")
1427 {
1428 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1429 }
1430 else
1431 {
1432 BMCWEB_LOG_DEBUG << "Invalid property value for "
1433 "BootSourceOverrideMode: "
1434 << *bootType;
1435 messages::propertyValueNotInList(aResp->res, *bootType,
1436 "BootSourceOverrideMode");
1437 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001438 }
1439
1440 // Act on validated parameters
1441 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1442
1443 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001444 [aResp](const boost::system::error_code ec) {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001445 if (ec)
1446 {
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001447 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1448 if (ec.value() == boost::asio::error::host_unreachable)
1449 {
1450 messages::resourceNotFound(aResp->res, "Set", "BootType");
1451 return;
1452 }
1453 messages::internalError(aResp->res);
1454 return;
1455 }
1456 BMCWEB_LOG_DEBUG << "Boot type update done.";
1457 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001458 "xyz.openbmc_project.Settings",
1459 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001460 "org.freedesktop.DBus.Properties", "Set",
1461 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001462 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001463}
1464
1465/**
1466 * @brief Sets boot properties into DBUS object(s).
1467 *
1468 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001469 * @param[in] bootType The boot type to set.
1470 * @return Integer error code.
1471 */
1472inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1473 const std::optional<std::string>& bootEnable)
1474{
1475 if (!bootEnable)
1476 {
1477 return;
1478 }
1479 // Source target specified
1480 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1481
1482 bool bootOverrideEnable = false;
1483 bool bootOverridePersistent = false;
1484 // Figure out which DBUS interface and property to use
1485 if (*bootEnable == "Disabled")
1486 {
1487 bootOverrideEnable = false;
1488 }
1489 else if (*bootEnable == "Once")
1490 {
1491 bootOverrideEnable = true;
1492 bootOverridePersistent = false;
1493 }
1494 else if (*bootEnable == "Continuous")
1495 {
1496 bootOverrideEnable = true;
1497 bootOverridePersistent = true;
1498 }
1499 else
1500 {
George Liu0fda0f12021-11-16 10:06:17 +08001501 BMCWEB_LOG_DEBUG
1502 << "Invalid property value for BootSourceOverrideEnabled: "
1503 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001504 messages::propertyValueNotInList(aResp->res, *bootEnable,
1505 "BootSourceOverrideEnabled");
1506 return;
1507 }
1508
1509 // Act on validated parameters
1510 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1511
1512 crow::connections::systemBus->async_method_call(
1513 [aResp](const boost::system::error_code ec) {
1514 if (ec)
1515 {
1516 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1517 messages::internalError(aResp->res);
1518 return;
1519 }
1520 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
1521 },
1522 "xyz.openbmc_project.Settings",
1523 "/xyz/openbmc_project/control/host0/boot",
1524 "org.freedesktop.DBus.Properties", "Set",
1525 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001526 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001527
1528 if (!bootOverrideEnable)
1529 {
1530 return;
1531 }
1532
1533 // In case boot override is enabled we need to set correct value for the
1534 // 'one_time' enable DBus interface
1535 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1536 << bootOverridePersistent;
1537
1538 crow::connections::systemBus->async_method_call(
1539 [aResp](const boost::system::error_code ec) {
1540 if (ec)
1541 {
1542 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1543 messages::internalError(aResp->res);
1544 return;
1545 }
1546 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
1547 },
1548 "xyz.openbmc_project.Settings",
1549 "/xyz/openbmc_project/control/host0/boot/one_time",
1550 "org.freedesktop.DBus.Properties", "Set",
1551 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001552 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001553}
1554
1555/**
1556 * @brief Sets boot properties into DBUS object(s).
1557 *
1558 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301559 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301560 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001561 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301562 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001563inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001564 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301565{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001566 std::string bootSourceStr;
1567 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001568
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001569 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301570 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001571 return;
1572 }
1573
1574 // Source target specified
1575 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1576 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001577 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1578 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001579 {
1580 BMCWEB_LOG_DEBUG
1581 << "Invalid property value for BootSourceOverrideTarget: "
1582 << *bootSource;
1583 messages::propertyValueNotInList(aResp->res, *bootSource,
1584 "BootSourceTargetOverride");
1585 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001586 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301587
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001588 // Act on validated parameters
1589 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1590 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001591
1592 crow::connections::systemBus->async_method_call(
1593 [aResp](const boost::system::error_code ec) {
1594 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301595 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001596 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1597 messages::internalError(aResp->res);
1598 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301599 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001600 BMCWEB_LOG_DEBUG << "Boot source update done.";
1601 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001602 "xyz.openbmc_project.Settings",
1603 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001604 "org.freedesktop.DBus.Properties", "Set",
1605 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001606 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001607
1608 crow::connections::systemBus->async_method_call(
1609 [aResp](const boost::system::error_code ec) {
1610 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301611 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001612 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1613 messages::internalError(aResp->res);
1614 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301615 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001616 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1617 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001618 "xyz.openbmc_project.Settings",
1619 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001620 "org.freedesktop.DBus.Properties", "Set",
1621 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001622 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001623}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001624
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001625/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001626 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301627 *
1628 * @param[in] aResp Shared pointer for generating response message.
1629 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001630 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301631 * @param[in] bootEnable The boot override enable from incoming RF request.
1632 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001633 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301634 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001635
1636inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1637 const std::optional<std::string>& bootSource,
1638 const std::optional<std::string>& bootType,
1639 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301640{
1641 BMCWEB_LOG_DEBUG << "Set boot information.";
1642
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001643 setBootModeOrSource(aResp, bootSource);
1644 setBootType(aResp, bootType);
1645 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301646}
1647
George Liuc6a620f2020-04-10 17:18:11 +08001648/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001649 * @brief Sets AssetTag
1650 *
1651 * @param[in] aResp Shared pointer for generating response message.
1652 * @param[in] assetTag "AssetTag" from request.
1653 *
1654 * @return None.
1655 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001656inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001657 const std::string& assetTag)
1658{
1659 crow::connections::systemBus->async_method_call(
1660 [aResp, assetTag](
1661 const boost::system::error_code ec,
1662 const std::vector<std::pair<
1663 std::string,
1664 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1665 subtree) {
1666 if (ec)
1667 {
1668 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1669 messages::internalError(aResp->res);
1670 return;
1671 }
Ed Tanous26f69762022-01-25 09:49:11 -08001672 if (subtree.empty())
Gunnar Mills98e386e2020-10-30 14:58:09 -05001673 {
1674 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1675 messages::internalError(aResp->res);
1676 return;
1677 }
1678 // Assume only 1 system D-Bus object
1679 // Throw an error if there is more than 1
1680 if (subtree.size() > 1)
1681 {
1682 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1683 messages::internalError(aResp->res);
1684 return;
1685 }
1686 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1687 {
1688 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1689 messages::internalError(aResp->res);
1690 return;
1691 }
1692
1693 const std::string& path = subtree[0].first;
1694 const std::string& service = subtree[0].second.begin()->first;
1695
1696 if (service.empty())
1697 {
1698 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1699 messages::internalError(aResp->res);
1700 return;
1701 }
1702
1703 crow::connections::systemBus->async_method_call(
1704 [aResp](const boost::system::error_code ec2) {
1705 if (ec2)
1706 {
1707 BMCWEB_LOG_DEBUG
1708 << "D-Bus response error on AssetTag Set " << ec2;
1709 messages::internalError(aResp->res);
1710 return;
1711 }
1712 },
1713 service, path, "org.freedesktop.DBus.Properties", "Set",
1714 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
Ed Tanous168e20c2021-12-13 14:39:53 -08001715 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001716 },
1717 "xyz.openbmc_project.ObjectMapper",
1718 "/xyz/openbmc_project/object_mapper",
1719 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1720 "/xyz/openbmc_project/inventory", int32_t(0),
1721 std::array<const char*, 1>{
1722 "xyz.openbmc_project.Inventory.Item.System"});
1723}
1724
1725/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001726 * @brief Sets automaticRetry (Auto Reboot)
1727 *
1728 * @param[in] aResp Shared pointer for generating response message.
1729 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1730 *
1731 * @return None.
1732 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001733inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001734 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001735{
1736 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1737
1738 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001739 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001740
1741 if (automaticRetryConfig == "Disabled")
1742 {
1743 autoRebootEnabled = false;
1744 }
1745 else if (automaticRetryConfig == "RetryAttempts")
1746 {
1747 autoRebootEnabled = true;
1748 }
1749 else
1750 {
George Liu0fda0f12021-11-16 10:06:17 +08001751 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001752 << automaticRetryConfig;
1753 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1754 "AutomaticRetryConfig");
1755 return;
1756 }
1757
1758 crow::connections::systemBus->async_method_call(
1759 [aResp](const boost::system::error_code ec) {
1760 if (ec)
1761 {
1762 messages::internalError(aResp->res);
1763 return;
1764 }
1765 },
1766 "xyz.openbmc_project.Settings",
1767 "/xyz/openbmc_project/control/host0/auto_reboot",
1768 "org.freedesktop.DBus.Properties", "Set",
1769 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001770 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001771}
1772
1773/**
George Liuc6a620f2020-04-10 17:18:11 +08001774 * @brief Sets power restore policy properties.
1775 *
1776 * @param[in] aResp Shared pointer for generating response message.
1777 * @param[in] policy power restore policy properties from request.
1778 *
1779 * @return None.
1780 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001781inline void
1782 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1783 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001784{
1785 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1786
1787 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001788 {"AlwaysOn",
1789 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1790 {"AlwaysOff",
1791 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1792 {"LastState",
1793 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001794
1795 std::string powerRestorPolicy;
1796
Gunnar Mills4e69c902021-01-05 19:50:11 -06001797 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001798 if (policyMapsIt == policyMaps.end())
1799 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001800 messages::propertyValueNotInList(aResp->res, policy,
1801 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001802 return;
1803 }
1804
1805 powerRestorPolicy = policyMapsIt->second;
1806
1807 crow::connections::systemBus->async_method_call(
1808 [aResp](const boost::system::error_code ec) {
1809 if (ec)
1810 {
1811 messages::internalError(aResp->res);
1812 return;
1813 }
1814 },
1815 "xyz.openbmc_project.Settings",
1816 "/xyz/openbmc_project/control/host0/power_restore_policy",
1817 "org.freedesktop.DBus.Properties", "Set",
1818 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001819 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001820}
1821
AppaRao Pulia6349912019-10-18 17:16:08 +05301822#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1823/**
1824 * @brief Retrieves provisioning status
1825 *
1826 * @param[in] aResp Shared pointer for completing asynchronous calls.
1827 *
1828 * @return None.
1829 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001830inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301831{
1832 BMCWEB_LOG_DEBUG << "Get OEM information.";
1833 crow::connections::systemBus->async_method_call(
1834 [aResp](const boost::system::error_code ec,
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001835 const std::vector<
1836 std::pair<std::string, dbus::utility::DbusVariantType>>&
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001837 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301838 nlohmann::json& oemPFR =
1839 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001840 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1841 "#OemComputerSystem.OpenBmc";
1842 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1843
AppaRao Pulia6349912019-10-18 17:16:08 +05301844 if (ec)
1845 {
1846 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301847 // not an error, don't have to have the interface
1848 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301849 return;
1850 }
1851
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001852 const bool* provState = nullptr;
1853 const bool* lockState = nullptr;
AppaRao Puli6e3b67e2022-01-06 01:37:08 +00001854 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1855 property : propertiesList)
AppaRao Pulia6349912019-10-18 17:16:08 +05301856 {
1857 if (property.first == "UfmProvisioned")
1858 {
1859 provState = std::get_if<bool>(&property.second);
1860 }
1861 else if (property.first == "UfmLocked")
1862 {
1863 lockState = std::get_if<bool>(&property.second);
1864 }
1865 }
1866
1867 if ((provState == nullptr) || (lockState == nullptr))
1868 {
1869 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1870 messages::internalError(aResp->res);
1871 return;
1872 }
1873
AppaRao Pulia6349912019-10-18 17:16:08 +05301874 if (*provState == true)
1875 {
1876 if (*lockState == true)
1877 {
1878 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1879 }
1880 else
1881 {
1882 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1883 }
1884 }
1885 else
1886 {
1887 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1888 }
1889 },
1890 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1891 "org.freedesktop.DBus.Properties", "GetAll",
1892 "xyz.openbmc_project.PFR.Attributes");
1893}
1894#endif
1895
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301896/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001897 * @brief Translate the PowerMode to a response message.
1898 *
1899 * @param[in] aResp Shared pointer for generating response message.
1900 * @param[in] modeValue PowerMode value to be translated
1901 *
1902 * @return None.
1903 */
1904inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1905 const std::string& modeValue)
1906{
1907 std::string modeString;
1908
George Liu0fda0f12021-11-16 10:06:17 +08001909 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001910 {
1911 aResp->res.jsonValue["PowerMode"] = "Static";
1912 }
George Liu0fda0f12021-11-16 10:06:17 +08001913 else if (
1914 modeValue ==
1915 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001916 {
1917 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1918 }
George Liu0fda0f12021-11-16 10:06:17 +08001919 else if (modeValue ==
1920 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001921 {
1922 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1923 }
George Liu0fda0f12021-11-16 10:06:17 +08001924 else if (modeValue ==
1925 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001926 {
1927 aResp->res.jsonValue["PowerMode"] = "OEM";
1928 }
1929 else
1930 {
1931 // Any other values would be invalid
1932 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1933 messages::internalError(aResp->res);
1934 }
1935}
1936
1937/**
1938 * @brief Retrieves system power mode
1939 *
1940 * @param[in] aResp Shared pointer for generating response message.
1941 *
1942 * @return None.
1943 */
1944inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1945{
1946 BMCWEB_LOG_DEBUG << "Get power mode.";
1947
1948 // Get Power Mode object path:
1949 crow::connections::systemBus->async_method_call(
1950 [aResp](
1951 const boost::system::error_code ec,
1952 const std::vector<std::pair<
1953 std::string,
1954 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1955 subtree) {
1956 if (ec)
1957 {
1958 BMCWEB_LOG_DEBUG
1959 << "DBUS response error on Power.Mode GetSubTree " << ec;
1960 // This is an optional D-Bus object so just return if
1961 // error occurs
1962 return;
1963 }
1964 if (subtree.empty())
1965 {
1966 // As noted above, this is an optional interface so just return
1967 // if there is no instance found
1968 return;
1969 }
1970 if (subtree.size() > 1)
1971 {
1972 // More then one PowerMode object is not supported and is an
1973 // error
1974 BMCWEB_LOG_DEBUG
1975 << "Found more than 1 system D-Bus Power.Mode objects: "
1976 << subtree.size();
1977 messages::internalError(aResp->res);
1978 return;
1979 }
1980 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1981 {
1982 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1983 messages::internalError(aResp->res);
1984 return;
1985 }
1986 const std::string& path = subtree[0].first;
1987 const std::string& service = subtree[0].second.begin()->first;
1988 if (service.empty())
1989 {
1990 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1991 messages::internalError(aResp->res);
1992 return;
1993 }
1994 // Valid Power Mode object found, now read the current value
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001995 sdbusplus::asio::getProperty<std::string>(
1996 *crow::connections::systemBus, service, path,
1997 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Chris Cain3a2d04242021-05-28 16:57:10 -05001998 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001999 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002000 if (ec)
2001 {
2002 BMCWEB_LOG_DEBUG
2003 << "DBUS response error on PowerMode Get: " << ec;
2004 messages::internalError(aResp->res);
2005 return;
2006 }
2007
Chris Cain3a2d04242021-05-28 16:57:10 -05002008 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] =
2009 {"Static", "MaximumPerformance", "PowerSaving"};
2010
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002011 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2012 translatePowerMode(aResp, pmode);
2013 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002014 },
2015 "xyz.openbmc_project.ObjectMapper",
2016 "/xyz/openbmc_project/object_mapper",
2017 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2018 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2019}
2020
2021/**
2022 * @brief Validate the specified mode is valid and return the PowerMode
2023 * name associated with that string
2024 *
2025 * @param[in] aResp Shared pointer for generating response message.
2026 * @param[in] modeString String representing the desired PowerMode
2027 *
2028 * @return PowerMode value or empty string if mode is not valid
2029 */
2030inline std::string
2031 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2032 const std::string& modeString)
2033{
2034 std::string mode;
2035
2036 if (modeString == "Static")
2037 {
2038 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2039 }
2040 else if (modeString == "MaximumPerformance")
2041 {
George Liu0fda0f12021-11-16 10:06:17 +08002042 mode =
2043 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002044 }
2045 else if (modeString == "PowerSaving")
2046 {
2047 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2048 }
2049 else
2050 {
2051 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2052 }
2053 return mode;
2054}
2055
2056/**
2057 * @brief Sets system power mode.
2058 *
2059 * @param[in] aResp Shared pointer for generating response message.
2060 * @param[in] pmode System power mode from request.
2061 *
2062 * @return None.
2063 */
2064inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2065 const std::string& pmode)
2066{
2067 BMCWEB_LOG_DEBUG << "Set power mode.";
2068
2069 std::string powerMode = validatePowerMode(aResp, pmode);
2070 if (powerMode.empty())
2071 {
2072 return;
2073 }
2074
2075 // Get Power Mode object path:
2076 crow::connections::systemBus->async_method_call(
2077 [aResp, powerMode](
2078 const boost::system::error_code ec,
2079 const std::vector<std::pair<
2080 std::string,
2081 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2082 subtree) {
2083 if (ec)
2084 {
2085 BMCWEB_LOG_DEBUG
2086 << "DBUS response error on Power.Mode GetSubTree " << ec;
2087 // This is an optional D-Bus object, but user attempted to patch
2088 messages::internalError(aResp->res);
2089 return;
2090 }
2091 if (subtree.empty())
2092 {
2093 // This is an optional D-Bus object, but user attempted to patch
2094 messages::resourceNotFound(aResp->res, "ComputerSystem",
2095 "PowerMode");
2096 return;
2097 }
2098 if (subtree.size() > 1)
2099 {
2100 // More then one PowerMode object is not supported and is an
2101 // error
2102 BMCWEB_LOG_DEBUG
2103 << "Found more than 1 system D-Bus Power.Mode objects: "
2104 << subtree.size();
2105 messages::internalError(aResp->res);
2106 return;
2107 }
2108 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2109 {
2110 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2111 messages::internalError(aResp->res);
2112 return;
2113 }
2114 const std::string& path = subtree[0].first;
2115 const std::string& service = subtree[0].second.begin()->first;
2116 if (service.empty())
2117 {
2118 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2119 messages::internalError(aResp->res);
2120 return;
2121 }
2122
2123 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2124 << path;
2125
2126 // Set the Power Mode property
2127 crow::connections::systemBus->async_method_call(
2128 [aResp](const boost::system::error_code ec) {
2129 if (ec)
2130 {
2131 messages::internalError(aResp->res);
2132 return;
2133 }
2134 },
2135 service, path, "org.freedesktop.DBus.Properties", "Set",
2136 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08002137 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002138 },
2139 "xyz.openbmc_project.ObjectMapper",
2140 "/xyz/openbmc_project/object_mapper",
2141 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2142 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2143}
2144
2145/**
Yong Li51709ff2019-09-30 14:13:04 +08002146 * @brief Translates watchdog timeout action DBUS property value to redfish.
2147 *
2148 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2149 *
2150 * @return Returns as a string, the timeout action in Redfish terms. If
2151 * translation cannot be done, returns an empty string.
2152 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002153inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002154{
2155 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2156 {
2157 return "None";
2158 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002159 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002160 {
2161 return "ResetSystem";
2162 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002163 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002164 {
2165 return "PowerDown";
2166 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002167 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002168 {
2169 return "PowerCycle";
2170 }
2171
2172 return "";
2173}
2174
2175/**
Yong Lic45f0082019-10-10 14:19:01 +08002176 *@brief Translates timeout action from Redfish to DBUS property value.
2177 *
2178 *@param[in] rfAction The timeout action in Redfish.
2179 *
2180 *@return Returns as a string, the time_out action as expected by DBUS.
2181 *If translation cannot be done, returns an empty string.
2182 */
2183
Ed Tanous23a21a12020-07-25 04:45:05 +00002184inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002185{
2186 if (rfAction == "None")
2187 {
2188 return "xyz.openbmc_project.State.Watchdog.Action.None";
2189 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002190 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002191 {
2192 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2193 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002194 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002195 {
2196 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2197 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002198 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002199 {
2200 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2201 }
2202
2203 return "";
2204}
2205
2206/**
Yong Li51709ff2019-09-30 14:13:04 +08002207 * @brief Retrieves host watchdog timer properties over DBUS
2208 *
2209 * @param[in] aResp Shared pointer for completing asynchronous calls.
2210 *
2211 * @return None.
2212 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002213inline void
2214 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002215{
2216 BMCWEB_LOG_DEBUG << "Get host watchodg";
2217 crow::connections::systemBus->async_method_call(
2218 [aResp](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002219 const PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08002220 if (ec)
2221 {
2222 // watchdog service is stopped
2223 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2224 return;
2225 }
2226
2227 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2228
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002229 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08002230 aResp->res.jsonValue["HostWatchdogTimer"];
2231
2232 // watchdog service is running/enabled
2233 hostWatchdogTimer["Status"]["State"] = "Enabled";
2234
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002235 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08002236 {
2237 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2238 if (property.first == "Enabled")
2239 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002240 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08002241
Ed Tanouse662eae2022-01-25 10:39:19 -08002242 if (state == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002243 {
2244 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002245 return;
Yong Li51709ff2019-09-30 14:13:04 +08002246 }
2247
2248 hostWatchdogTimer["FunctionEnabled"] = *state;
2249 }
2250 else if (property.first == "ExpireAction")
2251 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002252 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08002253 std::get_if<std::string>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002254 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002255 {
2256 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002257 return;
Yong Li51709ff2019-09-30 14:13:04 +08002258 }
2259
2260 std::string action = dbusToRfWatchdogAction(*s);
2261 if (action.empty())
2262 {
2263 messages::internalError(aResp->res);
Chicago Duan601af5e2021-04-15 16:59:25 +08002264 return;
Yong Li51709ff2019-09-30 14:13:04 +08002265 }
2266 hostWatchdogTimer["TimeoutAction"] = action;
2267 }
2268 }
2269 },
2270 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2271 "org.freedesktop.DBus.Properties", "GetAll",
2272 "xyz.openbmc_project.State.Watchdog");
2273}
2274
2275/**
Yong Lic45f0082019-10-10 14:19:01 +08002276 * @brief Sets Host WatchDog Timer properties.
2277 *
2278 * @param[in] aResp Shared pointer for generating response message.
2279 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2280 * RF request.
2281 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2282 *
2283 * @return None.
2284 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002285inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002286 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002287 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002288{
2289 BMCWEB_LOG_DEBUG << "Set host watchdog";
2290
2291 if (wdtTimeOutAction)
2292 {
2293 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2294 // check if TimeOut Action is Valid
2295 if (wdtTimeOutActStr.empty())
2296 {
2297 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2298 << *wdtTimeOutAction;
2299 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2300 "TimeoutAction");
2301 return;
2302 }
2303
2304 crow::connections::systemBus->async_method_call(
2305 [aResp](const boost::system::error_code ec) {
2306 if (ec)
2307 {
2308 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2309 messages::internalError(aResp->res);
2310 return;
2311 }
2312 },
2313 "xyz.openbmc_project.Watchdog",
2314 "/xyz/openbmc_project/watchdog/host0",
2315 "org.freedesktop.DBus.Properties", "Set",
2316 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002317 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002318 }
2319
2320 if (wdtEnable)
2321 {
2322 crow::connections::systemBus->async_method_call(
2323 [aResp](const boost::system::error_code ec) {
2324 if (ec)
2325 {
2326 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2327 messages::internalError(aResp->res);
2328 return;
2329 }
2330 },
2331 "xyz.openbmc_project.Watchdog",
2332 "/xyz/openbmc_project/watchdog/host0",
2333 "org.freedesktop.DBus.Properties", "Set",
2334 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002335 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002336 }
2337}
2338
Chris Cain37bbf982021-09-20 10:53:09 -05002339using ipsPropertiesType =
2340 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2341/**
2342 * @brief Parse the Idle Power Saver properties into json
2343 *
2344 * @param[in] aResp Shared pointer for completing asynchronous calls.
2345 * @param[in] properties IPS property data from DBus.
2346 *
2347 * @return true if successful
2348 */
Ed Tanousf6674222021-11-13 09:41:41 -08002349inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2350 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002351{
2352 for (const auto& property : properties)
2353 {
2354 if (property.first == "Enabled")
2355 {
2356 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002357 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002358 {
2359 return false;
2360 }
2361 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2362 }
2363 else if (property.first == "EnterUtilizationPercent")
2364 {
2365 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002366 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002367 {
2368 return false;
2369 }
2370 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2371 }
2372 else if (property.first == "EnterDwellTime")
2373 {
2374 // Convert Dbus time from milliseconds to seconds
2375 const uint64_t* timeMilliseconds =
2376 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002377 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002378 {
2379 return false;
2380 }
2381 const std::chrono::duration<uint64_t, std::milli> ms(
2382 *timeMilliseconds);
2383 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2384 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2385 .count();
2386 }
2387 else if (property.first == "ExitUtilizationPercent")
2388 {
2389 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002390 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002391 {
2392 return false;
2393 }
2394 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2395 }
2396 else if (property.first == "ExitDwellTime")
2397 {
2398 // Convert Dbus time from milliseconds to seconds
2399 const uint64_t* timeMilliseconds =
2400 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002401 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002402 {
2403 return false;
2404 }
2405 const std::chrono::duration<uint64_t, std::milli> ms(
2406 *timeMilliseconds);
2407 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2408 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2409 .count();
2410 }
2411 else
2412 {
2413 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2414 << property.first;
2415 }
2416 }
2417
2418 return true;
2419}
2420
2421/**
2422 * @brief Retrieves host watchdog timer properties over DBUS
2423 *
2424 * @param[in] aResp Shared pointer for completing asynchronous calls.
2425 *
2426 * @return None.
2427 */
2428inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2429{
2430 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2431
2432 // Get IdlePowerSaver object path:
2433 crow::connections::systemBus->async_method_call(
2434 [aResp](
2435 const boost::system::error_code ec,
2436 const std::vector<std::pair<
2437 std::string,
2438 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2439 subtree) {
2440 if (ec)
2441 {
2442 BMCWEB_LOG_DEBUG
2443 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2444 << ec;
2445 messages::internalError(aResp->res);
2446 return;
2447 }
2448 if (subtree.empty())
2449 {
2450 // This is an optional interface so just return
2451 // if there is no instance found
2452 BMCWEB_LOG_DEBUG << "No instances found";
2453 return;
2454 }
2455 if (subtree.size() > 1)
2456 {
2457 // More then one PowerIdlePowerSaver object is not supported and
2458 // is an error
2459 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2460 "Power.IdlePowerSaver objects: "
2461 << subtree.size();
2462 messages::internalError(aResp->res);
2463 return;
2464 }
2465 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2466 {
2467 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2468 messages::internalError(aResp->res);
2469 return;
2470 }
2471 const std::string& path = subtree[0].first;
2472 const std::string& service = subtree[0].second.begin()->first;
2473 if (service.empty())
2474 {
2475 BMCWEB_LOG_DEBUG
2476 << "Power.IdlePowerSaver service mapper error!";
2477 messages::internalError(aResp->res);
2478 return;
2479 }
2480
2481 // Valid IdlePowerSaver object found, now read the current values
2482 crow::connections::systemBus->async_method_call(
2483 [aResp](const boost::system::error_code ec,
2484 ipsPropertiesType& properties) {
2485 if (ec)
2486 {
2487 BMCWEB_LOG_ERROR
2488 << "DBUS response error on IdlePowerSaver GetAll: "
2489 << ec;
2490 messages::internalError(aResp->res);
2491 return;
2492 }
2493
Ed Tanouse05aec52022-01-25 10:28:56 -08002494 if (!parseIpsProperties(aResp, properties))
Chris Cain37bbf982021-09-20 10:53:09 -05002495 {
2496 messages::internalError(aResp->res);
2497 return;
2498 }
2499 },
2500 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2501 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
2502 },
2503 "xyz.openbmc_project.ObjectMapper",
2504 "/xyz/openbmc_project/object_mapper",
2505 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2506 std::array<const char*, 1>{
2507 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2508
2509 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2510}
2511
2512/**
2513 * @brief Sets Idle Power Saver properties.
2514 *
2515 * @param[in] aResp Shared pointer for generating response message.
2516 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2517 * RF request.
2518 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2519 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2520 * before entering idle state.
2521 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2522 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2523 * before exiting idle state
2524 *
2525 * @return None.
2526 */
2527inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2528 const std::optional<bool> ipsEnable,
2529 const std::optional<uint8_t> ipsEnterUtil,
2530 const std::optional<uint64_t> ipsEnterTime,
2531 const std::optional<uint8_t> ipsExitUtil,
2532 const std::optional<uint64_t> ipsExitTime)
2533{
2534 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2535
2536 // Get IdlePowerSaver object path:
2537 crow::connections::systemBus->async_method_call(
2538 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
2539 ipsExitTime](
2540 const boost::system::error_code ec,
2541 const std::vector<std::pair<
2542 std::string,
2543 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
2544 subtree) {
2545 if (ec)
2546 {
2547 BMCWEB_LOG_DEBUG
2548 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2549 << ec;
2550 messages::internalError(aResp->res);
2551 return;
2552 }
2553 if (subtree.empty())
2554 {
2555 // This is an optional D-Bus object, but user attempted to patch
2556 messages::resourceNotFound(aResp->res, "ComputerSystem",
2557 "IdlePowerSaver");
2558 return;
2559 }
2560 if (subtree.size() > 1)
2561 {
2562 // More then one PowerIdlePowerSaver object is not supported and
2563 // is an error
George Liu0fda0f12021-11-16 10:06:17 +08002564 BMCWEB_LOG_DEBUG
2565 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2566 << subtree.size();
Chris Cain37bbf982021-09-20 10:53:09 -05002567 messages::internalError(aResp->res);
2568 return;
2569 }
2570 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2571 {
2572 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2573 messages::internalError(aResp->res);
2574 return;
2575 }
2576 const std::string& path = subtree[0].first;
2577 const std::string& service = subtree[0].second.begin()->first;
2578 if (service.empty())
2579 {
2580 BMCWEB_LOG_DEBUG
2581 << "Power.IdlePowerSaver service mapper error!";
2582 messages::internalError(aResp->res);
2583 return;
2584 }
2585
2586 // Valid Power IdlePowerSaver object found, now set any values that
2587 // need to be updated
2588
2589 if (ipsEnable)
2590 {
2591 crow::connections::systemBus->async_method_call(
2592 [aResp](const boost::system::error_code ec) {
2593 if (ec)
2594 {
2595 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2596 messages::internalError(aResp->res);
2597 return;
2598 }
2599 },
2600 service, path, "org.freedesktop.DBus.Properties", "Set",
2601 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002602 "Enabled", dbus::utility::DbusVariantType(*ipsEnable));
Chris Cain37bbf982021-09-20 10:53:09 -05002603 }
2604 if (ipsEnterUtil)
2605 {
2606 crow::connections::systemBus->async_method_call(
2607 [aResp](const boost::system::error_code ec) {
2608 if (ec)
2609 {
2610 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2611 messages::internalError(aResp->res);
2612 return;
2613 }
2614 },
2615 service, path, "org.freedesktop.DBus.Properties", "Set",
2616 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2617 "EnterUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002618 dbus::utility::DbusVariantType(*ipsEnterUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002619 }
2620 if (ipsEnterTime)
2621 {
2622 // Convert from seconds into milliseconds for DBus
2623 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2624 crow::connections::systemBus->async_method_call(
2625 [aResp](const boost::system::error_code ec) {
2626 if (ec)
2627 {
2628 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2629 messages::internalError(aResp->res);
2630 return;
2631 }
2632 },
2633 service, path, "org.freedesktop.DBus.Properties", "Set",
2634 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002635 "EnterDwellTime",
2636 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002637 }
2638 if (ipsExitUtil)
2639 {
2640 crow::connections::systemBus->async_method_call(
2641 [aResp](const boost::system::error_code ec) {
2642 if (ec)
2643 {
2644 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2645 messages::internalError(aResp->res);
2646 return;
2647 }
2648 },
2649 service, path, "org.freedesktop.DBus.Properties", "Set",
2650 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2651 "ExitUtilizationPercent",
Ed Tanous168e20c2021-12-13 14:39:53 -08002652 dbus::utility::DbusVariantType(*ipsExitUtil));
Chris Cain37bbf982021-09-20 10:53:09 -05002653 }
2654 if (ipsExitTime)
2655 {
2656 // Convert from seconds into milliseconds for DBus
2657 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2658 crow::connections::systemBus->async_method_call(
2659 [aResp](const boost::system::error_code ec) {
2660 if (ec)
2661 {
2662 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2663 messages::internalError(aResp->res);
2664 return;
2665 }
2666 },
2667 service, path, "org.freedesktop.DBus.Properties", "Set",
2668 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous168e20c2021-12-13 14:39:53 -08002669 "ExitDwellTime",
2670 dbus::utility::DbusVariantType(timeMilliseconds));
Chris Cain37bbf982021-09-20 10:53:09 -05002671 }
2672 },
2673 "xyz.openbmc_project.ObjectMapper",
2674 "/xyz/openbmc_project/object_mapper",
2675 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2676 std::array<const char*, 1>{
2677 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2678
2679 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2680}
2681
Yong Lic45f0082019-10-10 14:19:01 +08002682/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002683 * SystemsCollection derived class for delivering ComputerSystems Collection
2684 * Schema
2685 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002686inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002687{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002688 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002689 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002690 .methods(boost::beast::http::verb::get)(
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002691 [](const crow::Request& /*req*/,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002692 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2693 asyncResp->res.jsonValue["@odata.type"] =
2694 "#ComputerSystemCollection.ComputerSystemCollection";
2695 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2696 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002697
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002698 sdbusplus::asio::getProperty<std::string>(
2699 *crow::connections::systemBus,
2700 "xyz.openbmc_project.Settings",
2701 "/xyz/openbmc_project/network/hypervisor",
2702 "xyz.openbmc_project.Network.SystemConfiguration",
2703 "HostName",
2704 [asyncResp](const boost::system::error_code ec,
2705 const std::string& /*hostName*/) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002706 nlohmann::json& ifaceArray =
2707 asyncResp->res.jsonValue["Members"];
2708 ifaceArray = nlohmann::json::array();
2709 auto& count =
2710 asyncResp->res.jsonValue["Members@odata.count"];
2711 ifaceArray.push_back(
2712 {{"@odata.id", "/redfish/v1/Systems/system"}});
2713 count = ifaceArray.size();
2714 if (!ec)
2715 {
2716 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2717 ifaceArray.push_back(
2718 {{"@odata.id",
2719 "/redfish/v1/Systems/hypervisor"}});
2720 count = ifaceArray.size();
2721 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07002722 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002723 });
2724}
Sunitha Harish462023a2020-02-19 08:34:59 -06002725
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002726/**
2727 * Function transceives data with dbus directly.
2728 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002729inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002730{
2731 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2732 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2733 constexpr char const* interfaceName =
2734 "xyz.openbmc_project.Control.Host.NMI";
2735 constexpr char const* method = "NMI";
2736
2737 crow::connections::systemBus->async_method_call(
2738 [asyncResp](const boost::system::error_code ec) {
2739 if (ec)
2740 {
2741 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2742 messages::internalError(asyncResp->res);
2743 return;
2744 }
2745 messages::success(asyncResp->res);
2746 },
2747 serviceName, objectPath, interfaceName, method);
2748}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002749
2750/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002751 * SystemActionsReset class supports handle POST method for Reset action.
2752 * The class retrieves and sends data directly to D-Bus.
2753 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002754inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002755{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002756 /**
2757 * Function handles POST method request.
2758 * Analyzes POST body message before sends Reset request data to D-Bus.
2759 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002760 BMCWEB_ROUTE(app,
2761 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002762 .privileges(redfish::privileges::postComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002763 .methods(
2764 boost::beast::http::verb::
2765 post)([](const crow::Request& req,
2766 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2767 std::string resetType;
Willy Tu15ed6782021-12-14 11:03:16 -08002768 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2769 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002770 {
2771 return;
2772 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002773
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002774 // Get the command and host vs. chassis
2775 std::string command;
Ed Tanous543f4402022-01-06 13:12:53 -08002776 bool hostCommand = true;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002777 if ((resetType == "On") || (resetType == "ForceOn"))
2778 {
2779 command = "xyz.openbmc_project.State.Host.Transition.On";
2780 hostCommand = true;
2781 }
2782 else if (resetType == "ForceOff")
2783 {
2784 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2785 hostCommand = false;
2786 }
2787 else if (resetType == "ForceRestart")
2788 {
2789 command =
2790 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2791 hostCommand = true;
2792 }
2793 else if (resetType == "GracefulShutdown")
2794 {
2795 command = "xyz.openbmc_project.State.Host.Transition.Off";
2796 hostCommand = true;
2797 }
2798 else if (resetType == "GracefulRestart")
2799 {
George Liu0fda0f12021-11-16 10:06:17 +08002800 command =
2801 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002802 hostCommand = true;
2803 }
2804 else if (resetType == "PowerCycle")
2805 {
2806 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2807 hostCommand = true;
2808 }
2809 else if (resetType == "Nmi")
2810 {
2811 doNMI(asyncResp);
2812 return;
2813 }
2814 else
2815 {
2816 messages::actionParameterUnknown(asyncResp->res, "Reset",
2817 resetType);
2818 return;
2819 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002820
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002821 if (hostCommand)
2822 {
2823 crow::connections::systemBus->async_method_call(
2824 [asyncResp, resetType](const boost::system::error_code ec) {
2825 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002826 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002827 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2828 if (ec.value() ==
2829 boost::asio::error::invalid_argument)
2830 {
2831 messages::actionParameterNotSupported(
2832 asyncResp->res, resetType, "Reset");
2833 }
2834 else
2835 {
2836 messages::internalError(asyncResp->res);
2837 }
2838 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002839 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002840 messages::success(asyncResp->res);
2841 },
2842 "xyz.openbmc_project.State.Host",
2843 "/xyz/openbmc_project/state/host0",
2844 "org.freedesktop.DBus.Properties", "Set",
2845 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002846 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002847 }
2848 else
2849 {
2850 crow::connections::systemBus->async_method_call(
2851 [asyncResp, resetType](const boost::system::error_code ec) {
2852 if (ec)
Jason M. Billsd22c8392019-06-03 13:59:03 -07002853 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002854 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2855 if (ec.value() ==
2856 boost::asio::error::invalid_argument)
2857 {
2858 messages::actionParameterNotSupported(
2859 asyncResp->res, resetType, "Reset");
2860 }
2861 else
2862 {
2863 messages::internalError(asyncResp->res);
2864 }
2865 return;
Jason M. Billsd22c8392019-06-03 13:59:03 -07002866 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002867 messages::success(asyncResp->res);
2868 },
2869 "xyz.openbmc_project.State.Chassis",
2870 "/xyz/openbmc_project/state/chassis0",
2871 "org.freedesktop.DBus.Properties", "Set",
2872 "xyz.openbmc_project.State.Chassis",
2873 "RequestedPowerTransition",
Ed Tanous168e20c2021-12-13 14:39:53 -08002874 dbus::utility::DbusVariantType{command});
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002875 }
2876 });
2877}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002878
2879/**
Ed Tanous66173382018-08-15 18:20:59 -07002880 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002881 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002883{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002884
Ed Tanous1abe55e2018-09-05 08:30:59 -07002885 /**
2886 * Functions triggers appropriate requests on DBus
2887 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002888 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002889 .privileges(redfish::privileges::getComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002890 .methods(
2891 boost::beast::http::verb::
2892 get)([](const crow::Request&,
2893 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2894 asyncResp->res.jsonValue["@odata.type"] =
Chris Cain37bbf982021-09-20 10:53:09 -05002895 "#ComputerSystem.v1_16_0.ComputerSystem";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002896 asyncResp->res.jsonValue["Name"] = "system";
2897 asyncResp->res.jsonValue["Id"] = "system";
2898 asyncResp->res.jsonValue["SystemType"] = "Physical";
2899 asyncResp->res.jsonValue["Description"] = "Computer System";
2900 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2901 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2902 "Disabled";
2903 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2904 uint64_t(0);
2905 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2906 "Disabled";
2907 asyncResp->res.jsonValue["@odata.id"] =
2908 "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002909
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002910 asyncResp->res.jsonValue["Processors"] = {
2911 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
2912 asyncResp->res.jsonValue["Memory"] = {
2913 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
2914 asyncResp->res.jsonValue["Storage"] = {
2915 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08002916
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002917 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
2918 {"target",
2919 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
2920 {"@Redfish.ActionInfo",
2921 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002922
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002923 asyncResp->res.jsonValue["LogServices"] = {
2924 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002925
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002926 asyncResp->res.jsonValue["Bios"] = {
2927 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
Carol Wangd82a3ac2019-11-21 13:56:38 +08002928
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002929 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
2930 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002931
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002932 asyncResp->res.jsonValue["Status"] = {
2933 {"Health", "OK"},
2934 {"State", "Enabled"},
2935 };
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002936
2937 // Fill in SerialConsole info
2938 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
2939 15;
2940 asyncResp->res.jsonValue["SerialConsole"]["IPMI"] = {
2941 {"ServiceEnabled", true},
2942 };
2943 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2944 asyncResp->res.jsonValue["SerialConsole"]["SSH"] = {
2945 {"ServiceEnabled", true},
2946 {"Port", 2200},
2947 // https://github.com/openbmc/docs/blob/master/console.md
2948 {"HotKeySequenceDisplay", "Press ~. to exit console"},
2949 };
2950
2951#ifdef BMCWEB_ENABLE_KVM
2952 // Fill in GraphicalConsole info
2953 asyncResp->res.jsonValue["GraphicalConsole"] = {
2954 {"ServiceEnabled", true},
2955 {"MaxConcurrentSessions", 4},
2956 {"ConnectTypesSupported", {"KVMIP"}},
2957 };
2958#endif // BMCWEB_ENABLE_KVM
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002959 constexpr const std::array<const char*, 4> inventoryForSystems = {
2960 "xyz.openbmc_project.Inventory.Item.Dimm",
2961 "xyz.openbmc_project.Inventory.Item.Cpu",
2962 "xyz.openbmc_project.Inventory.Item.Drive",
2963 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002964
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002965 auto health = std::make_shared<HealthPopulate>(asyncResp);
2966 crow::connections::systemBus->async_method_call(
2967 [health](const boost::system::error_code ec,
Ed Tanous914e2d52022-01-07 11:38:34 -08002968 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002969 if (ec)
2970 {
2971 // no inventory
2972 return;
2973 }
2974
Ed Tanous914e2d52022-01-07 11:38:34 -08002975 health->inventory = resp;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002976 },
2977 "xyz.openbmc_project.ObjectMapper",
2978 "/xyz/openbmc_project/object_mapper",
2979 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2980 int32_t(0), inventoryForSystems);
2981
2982 health->populate();
2983
2984 getMainChassisId(
2985 asyncResp, [](const std::string& chassisId,
2986 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2987 aRsp->res.jsonValue["Links"]["Chassis"] = {
2988 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2989 });
2990
2991 getLocationIndicatorActive(asyncResp);
2992 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2993 getIndicatorLedState(asyncResp);
2994 getComputerSystem(asyncResp, health);
2995 getHostState(asyncResp);
2996 getBootProperties(asyncResp);
2997 getBootProgress(asyncResp);
2998 getPCIeDeviceList(asyncResp, "PCIeDevices");
2999 getHostWatchdogTimer(asyncResp);
3000 getPowerRestorePolicy(asyncResp);
3001 getAutomaticRetry(asyncResp);
3002 getLastResetTime(asyncResp);
3003#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
3004 getProvisioningStatus(asyncResp);
3005#endif
Ali Ahmed19817712021-06-29 17:01:52 -05003006 getTrustedModuleRequiredToBoot(asyncResp);
Chris Cain3a2d04242021-05-28 16:57:10 -05003007 getPowerMode(asyncResp);
Chris Cain37bbf982021-09-20 10:53:09 -05003008 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003009 });
3010 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07003011 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003012 .methods(boost::beast::http::verb::patch)(
3013 [](const crow::Request& req,
3014 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3015 std::optional<bool> locationIndicatorActive;
3016 std::optional<std::string> indicatorLed;
3017 std::optional<nlohmann::json> bootProps;
3018 std::optional<nlohmann::json> wdtTimerProps;
3019 std::optional<std::string> assetTag;
3020 std::optional<std::string> powerRestorePolicy;
Chris Cain3a2d04242021-05-28 16:57:10 -05003021 std::optional<std::string> powerMode;
Chris Cain37bbf982021-09-20 10:53:09 -05003022 std::optional<nlohmann::json> ipsProps;
Willy Tu15ed6782021-12-14 11:03:16 -08003023 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003024 req, asyncResp->res, "IndicatorLED", indicatorLed,
3025 "LocationIndicatorActive", locationIndicatorActive,
3026 "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
3027 "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
Chris Cain37bbf982021-09-20 10:53:09 -05003028 assetTag, "PowerMode", powerMode, "IdlePowerSaver",
3029 ipsProps))
James Feistb49ac872019-05-21 15:12:01 -07003030 {
James Feistb49ac872019-05-21 15:12:01 -07003031 return;
3032 }
3033
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003034 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003035
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003036 if (assetTag)
3037 {
3038 setAssetTag(asyncResp, *assetTag);
3039 }
James Feistb49ac872019-05-21 15:12:01 -07003040
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003041 if (wdtTimerProps)
3042 {
3043 std::optional<bool> wdtEnable;
3044 std::optional<std::string> wdtTimeOutAction;
3045
3046 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
3047 "FunctionEnabled", wdtEnable,
3048 "TimeoutAction", wdtTimeOutAction))
3049 {
3050 return;
3051 }
3052 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3053 }
3054
3055 if (bootProps)
3056 {
3057 std::optional<std::string> bootSource;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003058 std::optional<std::string> bootType;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003059 std::optional<std::string> bootEnable;
3060 std::optional<std::string> automaticRetryConfig;
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003061 std::optional<bool> trustedModuleRequiredToBoot;
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003062
3063 if (!json_util::readJson(
3064 *bootProps, asyncResp->res,
3065 "BootSourceOverrideTarget", bootSource,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003066 "BootSourceOverrideMode", bootType,
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003067 "BootSourceOverrideEnabled", bootEnable,
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003068 "AutomaticRetryConfig", automaticRetryConfig,
3069 "TrustedModuleRequiredToBoot",
3070 trustedModuleRequiredToBoot))
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003071 {
3072 return;
3073 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003074
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03003075 if (bootSource || bootType || bootEnable)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003076 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03003077 setBootProperties(asyncResp, bootSource, bootType,
3078 bootEnable);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003079 }
3080 if (automaticRetryConfig)
3081 {
3082 setAutomaticRetry(asyncResp, *automaticRetryConfig);
3083 }
Ali Ahmedac7e1e02021-09-15 21:02:57 -05003084
3085 if (trustedModuleRequiredToBoot)
3086 {
3087 setTrustedModuleRequiredToBoot(
3088 asyncResp, *trustedModuleRequiredToBoot);
3089 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003090 }
3091
3092 if (locationIndicatorActive)
3093 {
3094 setLocationIndicatorActive(asyncResp,
3095 *locationIndicatorActive);
3096 }
3097
3098 // TODO (Gunnar): Remove IndicatorLED after enough time has
3099 // passed
3100 if (indicatorLed)
3101 {
3102 setIndicatorLedState(asyncResp, *indicatorLed);
3103 asyncResp->res.addHeader(
3104 boost::beast::http::field::warning,
3105 "299 - \"IndicatorLED is deprecated. Use "
3106 "LocationIndicatorActive instead.\"");
3107 }
3108
3109 if (powerRestorePolicy)
3110 {
3111 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3112 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003113
3114 if (powerMode)
3115 {
3116 setPowerMode(asyncResp, *powerMode);
3117 }
Chris Cain37bbf982021-09-20 10:53:09 -05003118
3119 if (ipsProps)
3120 {
3121 std::optional<bool> ipsEnable;
3122 std::optional<uint8_t> ipsEnterUtil;
3123 std::optional<uint64_t> ipsEnterTime;
3124 std::optional<uint8_t> ipsExitUtil;
3125 std::optional<uint64_t> ipsExitTime;
3126
3127 if (!json_util::readJson(
3128 *ipsProps, asyncResp->res, "Enabled", ipsEnable,
3129 "EnterUtilizationPercent", ipsEnterUtil,
3130 "EnterDwellTimeSeconds", ipsEnterTime,
3131 "ExitUtilizationPercent", ipsExitUtil,
3132 "ExitDwellTimeSeconds", ipsExitTime))
3133 {
3134 return;
3135 }
3136 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil,
3137 ipsEnterTime, ipsExitUtil, ipsExitTime);
3138 }
zhanghch058d1b46d2021-04-01 11:18:24 +08003139 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003140}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303141
3142/**
3143 * SystemResetActionInfo derived class for delivering Computer Systems
3144 * ResetType AllowableValues using ResetInfo schema.
3145 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003146inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303147{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303148
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303149 /**
3150 * Functions triggers appropriate requests on DBus
3151 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003152 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003153 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003154 .methods(boost::beast::http::verb::get)(
3155 [](const crow::Request&,
3156 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3157 asyncResp->res.jsonValue = {
3158 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
3159 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
3160 {"Name", "Reset Action Info"},
3161 {"Id", "ResetActionInfo"},
3162 {"Parameters",
3163 {{{"Name", "ResetType"},
3164 {"Required", true},
3165 {"DataType", "String"},
3166 {"AllowableValues",
3167 {"On", "ForceOff", "ForceOn", "ForceRestart",
3168 "GracefulRestart", "GracefulShutdown", "PowerCycle",
3169 "Nmi"}}}}}};
3170 });
3171}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003172} // namespace redfish