blob: 81db36b6282858289ee4ee3af4eddc35f01cfc24 [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
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070021#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070023#include "health.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060024#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080025#include "led.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070026#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080027#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080028#include "registries/privilege_registry.hpp"
29#include "utils/dbus_utils.hpp"
30#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050031#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080032#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070033#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080034
Andrew Geisslerfc903b32023-05-31 14:15:42 -040035#include <boost/asio/error.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070036#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080037#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070038#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070039#include <sdbusplus/asio/property.hpp>
Andrew Geisslerfc903b32023-05-31 14:15:42 -040040#include <sdbusplus/message.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020041#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042
George Liu7a1dbc42022-12-07 16:03:22 +080043#include <array>
44#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080045#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020046
Ed Tanous1abe55e2018-09-05 08:30:59 -070047namespace redfish
48{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020049
Abhishek Patel5c3e9272021-06-24 10:11:33 -050050const static std::array<std::pair<std::string_view, std::string_view>, 2>
51 protocolToDBusForSystems{
52 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
53
Alpana Kumari9d3ae102019-04-12 06:49:32 -050054/**
55 * @brief Updates the Functional State of DIMMs
56 *
57 * @param[in] aResp Shared pointer for completing asynchronous calls
58 * @param[in] dimmState Dimm's Functional state, true/false
59 *
60 * @return None.
61 */
zhanghch058d1b46d2021-04-01 11:18:24 +080062inline void
63 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070064 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070066 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050067
Gunnar Mills4e0453b2020-07-08 14:00:30 -050068 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050069 // Update STATE only if previous State was DISABLED and current Dimm is
70 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070071 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050072 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
73 if (prevMemSummary == "Disabled")
74 {
Ed Tanouse05aec52022-01-25 10:28:56 -080075 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050076 {
77 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
78 "Enabled";
79 }
80 }
81}
82
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050083/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050084 * @brief Update "ProcessorSummary" "Status" "State" based on
85 * CPU Functional State
86 *
87 * @param[in] aResp Shared pointer for completing asynchronous calls
88 * @param[in] cpuFunctionalState is CPU functional true/false
89 *
90 * @return None.
91 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070092inline void
93 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
94 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050095{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070096 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050097
Ed Tanous02cad962022-06-30 16:50:15 -070098 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050099 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
100
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500101 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500102 // Update STATE only if previous State was Non_Functional and current CPU is
103 // Functional.
104 if (prevProcState == "Disabled")
105 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800106 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500107 {
108 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
109 "Enabled";
110 }
111 }
112}
113
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500114/*
115 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
116 *
117 * @param[in] aResp Shared pointer for completing asynchronous calls
118 * @param[in] cpuPresenceState CPU present or not
119 *
120 * @return None.
121 */
122inline void
123 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
124 bool isCpuPresent)
125{
126 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
127
128 if (isCpuPresent)
129 {
130 nlohmann::json& procCount =
131 aResp->res.jsonValue["ProcessorSummary"]["Count"];
132 auto* procCountPtr =
133 procCount.get_ptr<nlohmann::json::number_integer_t*>();
134 if (procCountPtr != nullptr)
135 {
136 // shouldn't be possible to be nullptr
137 *procCountPtr += 1;
138 }
139 }
140}
141
Ali Ahmed382d6472021-09-03 16:53:53 -0500142inline void getProcessorProperties(
143 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
144 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
145 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500146{
Ali Ahmed03fbed92021-09-03 02:33:43 -0500147 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
148
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200149 // TODO: Get Model
150
151 const uint16_t* coreCount = nullptr;
152
153 const bool success = sdbusplus::unpackPropertiesNoThrow(
154 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
155
156 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500157 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200158 messages::internalError(aResp->res);
159 return;
160 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500161
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200162 if (coreCount != nullptr)
163 {
164 nlohmann::json& coreCountJson =
165 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
166 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500167
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200168 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500169 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200170 coreCountJson = *coreCount;
171 }
172 else
173 {
174 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500175 }
176 }
177}
178
179/*
180 * @brief Get ProcessorSummary fields
181 *
182 * @param[in] aResp Shared pointer for completing asynchronous calls
183 * @param[in] service dbus service for Cpu Information
184 * @param[in] path dbus path for Cpu
185 *
186 * @return None.
187 */
188inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
189 const std::string& service,
190 const std::string& path)
191{
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800192 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500193 const bool cpuPresenceCheck) {
194 if (ec3)
195 {
196 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
197 return;
198 }
199 modifyCpuPresenceState(aResp, cpuPresenceCheck);
200 };
201
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500202 // Get the Presence of CPU
203 sdbusplus::asio::getProperty<bool>(
204 *crow::connections::systemBus, service, path,
205 "xyz.openbmc_project.Inventory.Item", "Present",
206 std::move(getCpuPresenceState));
207
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500208 if constexpr (bmcwebEnableProcMemStatus)
209 {
210 auto getCpuFunctionalState =
211 [aResp](const boost::system::error_code& ec3,
212 const bool cpuFunctionalCheck) {
213 if (ec3)
214 {
215 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
216 return;
217 }
218 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
219 };
Ali Ahmed382d6472021-09-03 16:53:53 -0500220
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500221 // Get the Functional State
222 sdbusplus::asio::getProperty<bool>(
223 *crow::connections::systemBus, service, path,
224 "xyz.openbmc_project.State.Decorator.OperationalStatus",
225 "Functional", std::move(getCpuFunctionalState));
226 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500227
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200228 sdbusplus::asio::getAllProperties(
229 *crow::connections::systemBus, service, path,
230 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500231 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800232 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800233 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700234 if (ec2)
235 {
236 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
237 messages::internalError(aResp->res);
238 return;
239 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500240 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200241 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500242}
243
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500244/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500245 * @brief processMemoryProperties fields
246 *
247 * @param[in] aResp Shared pointer for completing asynchronous calls
248 * @param[in] service dbus service for memory Information
249 * @param[in] path dbus path for Memory
250 * @param[in] DBUS properties for memory
251 *
252 * @return None.
253 */
254inline void
255 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500256 [[maybe_unused]] const std::string& service,
257 [[maybe_unused]] const std::string& path,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500258 const dbus::utility::DBusPropertiesMap& properties)
259{
260 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Dimm properties.";
261
262 if (properties.empty())
263 {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500264 if constexpr (bmcwebEnableProcMemStatus)
265 {
266 sdbusplus::asio::getProperty<bool>(
267 *crow::connections::systemBus, service, path,
268 "xyz.openbmc_project.State."
269 "Decorator.OperationalStatus",
270 "Functional",
271 [aResp](const boost::system::error_code& ec3, bool dimmState) {
272 if (ec3)
273 {
274 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
275 return;
276 }
277 updateDimmProperties(aResp, dimmState);
278 });
279 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500280 return;
281 }
282
283 const size_t* memorySizeInKB = nullptr;
284
285 const bool success = sdbusplus::unpackPropertiesNoThrow(
286 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
287 memorySizeInKB);
288
289 if (!success)
290 {
291 messages::internalError(aResp->res);
292 return;
293 }
294
295 if (memorySizeInKB != nullptr)
296 {
297 nlohmann::json& totalMemory =
298 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
299 const uint64_t* preValue = totalMemory.get_ptr<const uint64_t*>();
300 if (preValue == nullptr)
301 {
302 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
303 *memorySizeInKB / static_cast<size_t>(1024 * 1024);
304 }
305 else
306 {
307 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
308 *memorySizeInKB / static_cast<size_t>(1024 * 1024) + *preValue;
309 }
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500310 if constexpr (bmcwebEnableProcMemStatus)
311 {
312 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
313 "Enabled";
314 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500315 }
316}
317
318/*
319 * @brief Get getMemorySummary fields
320 *
321 * @param[in] aResp Shared pointer for completing asynchronous calls
322 * @param[in] service dbus service for memory Information
323 * @param[in] path dbus path for memory
324 *
325 * @return None.
326 */
327inline void getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
328 const std::string& service,
329 const std::string& path)
330{
331 sdbusplus::asio::getAllProperties(
332 *crow::connections::systemBus, service, path,
333 "xyz.openbmc_project.Inventory.Item.Dimm",
334 [aResp, service,
335 path](const boost::system::error_code& ec2,
336 const dbus::utility::DBusPropertiesMap& properties) {
337 if (ec2)
338 {
339 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
340 messages::internalError(aResp->res);
341 return;
342 }
343 processMemoryProperties(aResp, service, path, properties);
344 });
345}
346
347/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700348 * @brief Retrieves computer system properties over dbus
349 *
350 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500351 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700352 *
353 * @return None.
354 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700355inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800356 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700357 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700358{
Ed Tanous6c34de42018-08-29 13:37:36 -0700359 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800360 constexpr std::array<std::string_view, 5> interfaces = {
361 "xyz.openbmc_project.Inventory.Decorator.Asset",
362 "xyz.openbmc_project.Inventory.Item.Cpu",
363 "xyz.openbmc_project.Inventory.Item.Dimm",
364 "xyz.openbmc_project.Inventory.Item.System",
365 "xyz.openbmc_project.Common.UUID",
366 };
367 dbus::utility::getSubTree(
368 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800369 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800370 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800371 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700372 if (ec)
373 {
374 BMCWEB_LOG_DEBUG << "DBUS response error";
375 messages::internalError(aResp->res);
376 return;
377 }
378 // Iterate over all retrieved ObjectPaths.
379 for (const std::pair<
380 std::string,
381 std::vector<std::pair<std::string, std::vector<std::string>>>>&
382 object : subtree)
383 {
384 const std::string& path = object.first;
385 BMCWEB_LOG_DEBUG << "Got path: " << path;
386 const std::vector<std::pair<std::string, std::vector<std::string>>>&
387 connectionNames = object.second;
388 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700389 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700390 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700391 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700392
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500393 std::shared_ptr<HealthPopulate> memoryHealth = nullptr;
394 std::shared_ptr<HealthPopulate> cpuHealth = nullptr;
Ed Tanous002d39b2022-05-31 08:59:27 -0700395
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500396 if constexpr (bmcwebEnableProcMemStatus)
Willy Tu13451e32023-05-24 16:08:18 -0700397 {
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500398 memoryHealth = std::make_shared<HealthPopulate>(
399 aResp, "/MemorySummary/Status"_json_pointer);
Willy Tu13451e32023-05-24 16:08:18 -0700400 systemHealth->children.emplace_back(memoryHealth);
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500401
402 if constexpr (bmcwebEnableHealthPopulate)
403 {
404 cpuHealth = std::make_shared<HealthPopulate>(
405 aResp, "/ProcessorSummary/Status"_json_pointer);
406
407 systemHealth->children.emplace_back(cpuHealth);
408 }
Willy Tu13451e32023-05-24 16:08:18 -0700409 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700410
411 // This is not system, so check if it's cpu, dimm, UUID or
412 // BiosVer
413 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700414 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700415 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700416 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700417 if (interfaceName ==
418 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700419 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700420 BMCWEB_LOG_DEBUG
421 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500422
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500423 getMemorySummary(aResp, connection.first, path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700424
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500425 if constexpr (bmcwebEnableProcMemStatus)
426 {
427 memoryHealth->inventory.emplace_back(path);
428 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700429 }
430 else if (interfaceName ==
431 "xyz.openbmc_project.Inventory.Item.Cpu")
432 {
433 BMCWEB_LOG_DEBUG
434 << "Found Cpu, now get its properties.";
435
436 getProcessorSummary(aResp, connection.first, path);
437
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -0500438 if constexpr (bmcwebEnableProcMemStatus)
439 {
440 cpuHealth->inventory.emplace_back(path);
441 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700442 }
443 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
444 {
445 BMCWEB_LOG_DEBUG
446 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200447
448 sdbusplus::asio::getAllProperties(
449 *crow::connections::systemBus, connection.first,
450 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800451 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700452 const dbus::utility::DBusPropertiesMap&
453 properties) {
454 if (ec3)
455 {
456 BMCWEB_LOG_DEBUG << "DBUS response error "
457 << ec3;
458 messages::internalError(aResp->res);
459 return;
460 }
461 BMCWEB_LOG_DEBUG << "Got " << properties.size()
462 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700463
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200464 const std::string* uUID = nullptr;
465
466 const bool success =
467 sdbusplus::unpackPropertiesNoThrow(
468 dbus_utils::UnpackErrorPrinter(),
469 properties, "UUID", uUID);
470
471 if (!success)
472 {
473 messages::internalError(aResp->res);
474 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700475 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200476
477 if (uUID != nullptr)
478 {
479 std::string valueStr = *uUID;
480 if (valueStr.size() == 32)
481 {
482 valueStr.insert(8, 1, '-');
483 valueStr.insert(13, 1, '-');
484 valueStr.insert(18, 1, '-');
485 valueStr.insert(23, 1, '-');
486 }
487 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
488 aResp->res.jsonValue["UUID"] = valueStr;
489 }
490 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700491 }
492 else if (interfaceName ==
493 "xyz.openbmc_project.Inventory.Item.System")
494 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200495 sdbusplus::asio::getAllProperties(
496 *crow::connections::systemBus, connection.first,
497 path,
498 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800499 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 const dbus::utility::DBusPropertiesMap&
501 propertiesList) {
502 if (ec2)
503 {
504 // doesn't have to include this
505 // interface
506 return;
507 }
508 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
509 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200510
511 const std::string* partNumber = nullptr;
512 const std::string* serialNumber = nullptr;
513 const std::string* manufacturer = nullptr;
514 const std::string* model = nullptr;
515 const std::string* subModel = nullptr;
516
517 const bool success =
518 sdbusplus::unpackPropertiesNoThrow(
519 dbus_utils::UnpackErrorPrinter(),
520 propertiesList, "PartNumber", partNumber,
521 "SerialNumber", serialNumber,
522 "Manufacturer", manufacturer, "Model",
523 model, "SubModel", subModel);
524
525 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700526 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200527 messages::internalError(aResp->res);
528 return;
529 }
530
531 if (partNumber != nullptr)
532 {
533 aResp->res.jsonValue["PartNumber"] =
534 *partNumber;
535 }
536
537 if (serialNumber != nullptr)
538 {
539 aResp->res.jsonValue["SerialNumber"] =
540 *serialNumber;
541 }
542
543 if (manufacturer != nullptr)
544 {
545 aResp->res.jsonValue["Manufacturer"] =
546 *manufacturer;
547 }
548
549 if (model != nullptr)
550 {
551 aResp->res.jsonValue["Model"] = *model;
552 }
553
554 if (subModel != nullptr)
555 {
556 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700557 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500558
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700560 sw_util::populateSoftwareInformation(
561 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700562 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200563 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700564
Ed Tanous002d39b2022-05-31 08:59:27 -0700565 sdbusplus::asio::getProperty<std::string>(
566 *crow::connections::systemBus, connection.first,
567 path,
568 "xyz.openbmc_project.Inventory.Decorator."
569 "AssetTag",
570 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800571 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700572 const std::string& value) {
573 if (ec2)
574 {
575 // doesn't have to include this
576 // interface
577 return;
578 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700579
Ed Tanous002d39b2022-05-31 08:59:27 -0700580 aResp->res.jsonValue["AssetTag"] = value;
581 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700582 }
583 }
584 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700585 }
Ed Tanous66173382018-08-15 18:20:59 -0700586 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700587}
588
589/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700590 * @brief Retrieves host state properties over dbus
591 *
592 * @param[in] aResp Shared pointer for completing asynchronous calls.
593 *
594 * @return None.
595 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800596inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700597{
598 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700599 sdbusplus::asio::getProperty<std::string>(
600 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
601 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
602 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800603 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700604 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700605 if (ec)
606 {
607 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700608 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700609 // Service not available, no error, just don't return
610 // host state info
611 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700612 return;
613 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700614 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
615 messages::internalError(aResp->res);
616 return;
617 }
Ed Tanous66173382018-08-15 18:20:59 -0700618
Ed Tanous002d39b2022-05-31 08:59:27 -0700619 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
620 // Verify Host State
621 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
622 {
623 aResp->res.jsonValue["PowerState"] = "On";
624 aResp->res.jsonValue["Status"]["State"] = "Enabled";
625 }
626 else if (hostState ==
627 "xyz.openbmc_project.State.Host.HostState.Quiesced")
628 {
629 aResp->res.jsonValue["PowerState"] = "On";
630 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
631 }
632 else if (hostState ==
633 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
634 {
635 aResp->res.jsonValue["PowerState"] = "On";
636 aResp->res.jsonValue["Status"]["State"] = "InTest";
637 }
638 else if (
639 hostState ==
640 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
641 {
642 aResp->res.jsonValue["PowerState"] = "PoweringOn";
643 aResp->res.jsonValue["Status"]["State"] = "Starting";
644 }
645 else if (hostState ==
646 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
647 {
648 aResp->res.jsonValue["PowerState"] = "PoweringOff";
649 aResp->res.jsonValue["Status"]["State"] = "Disabled";
650 }
651 else
652 {
653 aResp->res.jsonValue["PowerState"] = "Off";
654 aResp->res.jsonValue["Status"]["State"] = "Disabled";
655 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700656 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700657}
658
659/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500660 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661 *
662 * @param[in] dbusSource The boot source in DBUS speak.
663 *
664 * @return Returns as a string, the boot source in Redfish terms. If translation
665 * cannot be done, returns an empty string.
666 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000667inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530668{
669 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
670 {
671 return "None";
672 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700673 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530674 {
675 return "Hdd";
676 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700677 if (dbusSource ==
678 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530679 {
680 return "Cd";
681 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700682 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530683 {
684 return "Pxe";
685 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700686 if (dbusSource ==
687 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700688 {
689 return "Usb";
690 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700691 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530692}
693
694/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300695 * @brief Translates boot type DBUS property value to redfish.
696 *
697 * @param[in] dbusType The boot type in DBUS speak.
698 *
699 * @return Returns as a string, the boot type in Redfish terms. If translation
700 * cannot be done, returns an empty string.
701 */
702inline std::string dbusToRfBootType(const std::string& dbusType)
703{
704 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
705 {
706 return "Legacy";
707 }
708 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
709 {
710 return "UEFI";
711 }
712 return "";
713}
714
715/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500716 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530717 *
718 * @param[in] dbusMode The boot mode in DBUS speak.
719 *
720 * @return Returns as a string, the boot mode in Redfish terms. If translation
721 * cannot be done, returns an empty string.
722 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000723inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530724{
725 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
726 {
727 return "None";
728 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700729 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530730 {
731 return "Diags";
732 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700733 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530734 {
735 return "BiosSetup";
736 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700737 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530738}
739
740/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600741 * @brief Translates boot progress DBUS property value to redfish.
742 *
743 * @param[in] dbusBootProgress The boot progress in DBUS speak.
744 *
745 * @return Returns as a string, the boot progress in Redfish terms. If
746 * translation cannot be done, returns "None".
747 */
748inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
749{
750 // Now convert the D-Bus BootProgress to the appropriate Redfish
751 // enum
752 std::string rfBpLastState = "None";
753 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
754 "ProgressStages.Unspecified")
755 {
756 rfBpLastState = "None";
757 }
758 else if (dbusBootProgress ==
759 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
760 "PrimaryProcInit")
761 {
762 rfBpLastState = "PrimaryProcessorInitializationStarted";
763 }
764 else if (dbusBootProgress ==
765 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
766 "BusInit")
767 {
768 rfBpLastState = "BusInitializationStarted";
769 }
770 else if (dbusBootProgress ==
771 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
772 "MemoryInit")
773 {
774 rfBpLastState = "MemoryInitializationStarted";
775 }
776 else if (dbusBootProgress ==
777 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
778 "SecondaryProcInit")
779 {
780 rfBpLastState = "SecondaryProcessorInitializationStarted";
781 }
782 else if (dbusBootProgress ==
783 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
784 "PCIInit")
785 {
786 rfBpLastState = "PCIResourceConfigStarted";
787 }
788 else if (dbusBootProgress ==
789 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
790 "SystemSetup")
791 {
792 rfBpLastState = "SetupEntered";
793 }
794 else if (dbusBootProgress ==
795 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
796 "SystemInitComplete")
797 {
798 rfBpLastState = "SystemHardwareInitializationComplete";
799 }
800 else if (dbusBootProgress ==
801 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
802 "OSStart")
803 {
804 rfBpLastState = "OSBootStarted";
805 }
806 else if (dbusBootProgress ==
807 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
808 "OSRunning")
809 {
810 rfBpLastState = "OSRunning";
811 }
812 else
813 {
814 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
815 << dbusBootProgress;
816 // Just return the default
817 }
818 return rfBpLastState;
819}
820
821/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500822 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530823 *
824 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700825 * @param[out] bootSource The DBus source
826 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530827 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700828 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530829 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800830inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500831 const std::string& rfSource,
832 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530833{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300834 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
835 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700836
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530837 if (rfSource == "None")
838 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700839 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530840 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700841 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530842 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700843 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
844 }
845 else if (rfSource == "Hdd")
846 {
847 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
848 }
849 else if (rfSource == "Diags")
850 {
851 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
852 }
853 else if (rfSource == "Cd")
854 {
855 bootSource =
856 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
857 }
858 else if (rfSource == "BiosSetup")
859 {
860 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530861 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700862 else if (rfSource == "Usb")
863 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700864 bootSource =
865 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700866 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530867 else
868 {
George Liu0fda0f12021-11-16 10:06:17 +0800869 BMCWEB_LOG_DEBUG
870 << "Invalid property value for BootSourceOverrideTarget: "
871 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700872 messages::propertyValueNotInList(aResp->res, rfSource,
873 "BootSourceTargetOverride");
874 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530875 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700876 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530877}
Ali Ahmed19817712021-06-29 17:01:52 -0500878
Andrew Geissler978b8802020-11-19 13:36:40 -0600879/**
880 * @brief Retrieves boot progress of the system
881 *
882 * @param[in] aResp Shared pointer for generating response message.
883 *
884 * @return None.
885 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800886inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600887{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700888 sdbusplus::asio::getProperty<std::string>(
889 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
890 "/xyz/openbmc_project/state/host0",
891 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800892 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700893 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700894 if (ec)
895 {
896 // BootProgress is an optional object so just do nothing if
897 // not found
898 return;
899 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600900
Ed Tanous002d39b2022-05-31 08:59:27 -0700901 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600902
Ed Tanous002d39b2022-05-31 08:59:27 -0700903 aResp->res.jsonValue["BootProgress"]["LastState"] =
904 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700905 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600906}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530907
908/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000909 * @brief Retrieves boot progress Last Update of the system
910 *
911 * @param[in] aResp Shared pointer for generating response message.
912 *
913 * @return None.
914 */
915inline void getBootProgressLastStateTime(
916 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
917{
918 sdbusplus::asio::getProperty<uint64_t>(
919 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
920 "/xyz/openbmc_project/state/host0",
921 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800922 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000923 const uint64_t lastStateTime) {
924 if (ec)
925 {
926 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
927 return;
928 }
929
930 // BootProgressLastUpdate is the last time the BootProgress property
931 // was updated. The time is the Epoch time, number of microseconds
932 // since 1 Jan 1970 00::00::00 UTC."
933 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
934 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
935
936 // Convert to ISO 8601 standard
937 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
938 redfish::time_utils::getDateTimeUintUs(lastStateTime);
939 });
940}
941
942/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300943 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300944 *
945 * @param[in] aResp Shared pointer for generating response message.
946 *
947 * @return None.
948 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300949
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300950inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300951{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700952 sdbusplus::asio::getProperty<std::string>(
953 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
954 "/xyz/openbmc_project/control/host0/boot",
955 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800956 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700957 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700958 if (ec)
959 {
960 // not an error, don't have to have the interface
961 return;
962 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300963
Ed Tanous002d39b2022-05-31 08:59:27 -0700964 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300965
Ed Tanous002d39b2022-05-31 08:59:27 -0700966 aResp->res.jsonValue["Boot"]
967 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700968 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300969
Ed Tanous002d39b2022-05-31 08:59:27 -0700970 auto rfType = dbusToRfBootType(bootType);
971 if (rfType.empty())
972 {
973 messages::internalError(aResp->res);
974 return;
975 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300976
Ed Tanous002d39b2022-05-31 08:59:27 -0700977 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700978 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300979}
980
981/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300982 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530983 *
984 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985 *
986 * @return None.
987 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300988
989inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700991 sdbusplus::asio::getProperty<std::string>(
992 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
993 "/xyz/openbmc_project/control/host0/boot",
994 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800995 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700996 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700997 if (ec)
998 {
999 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1000 messages::internalError(aResp->res);
1001 return;
1002 }
1003
1004 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
1005
1006 aResp->res
1007 .jsonValue["Boot"]
1008 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
1009 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
1010
1011 if (bootModeStr !=
1012 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1013 {
1014 auto rfMode = dbusToRfBootMode(bootModeStr);
1015 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301016 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001017 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
1018 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001020 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001021 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301022}
1023
1024/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001025 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301026 *
1027 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301028 *
1029 * @return None.
1030 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001031
1032inline void
1033 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301034{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001035 sdbusplus::asio::getProperty<std::string>(
1036 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1037 "/xyz/openbmc_project/control/host0/boot",
1038 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001039 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001040 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001041 if (ec)
1042 {
1043 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001044 if (ec.value() == boost::asio::error::host_unreachable)
1045 {
1046 return;
1047 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001048 messages::internalError(aResp->res);
1049 return;
1050 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301051
Ed Tanous002d39b2022-05-31 08:59:27 -07001052 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301053
Ed Tanous002d39b2022-05-31 08:59:27 -07001054 auto rfSource = dbusToRfBootSource(bootSourceStr);
1055 if (!rfSource.empty())
1056 {
1057 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1058 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001059
Ed Tanous002d39b2022-05-31 08:59:27 -07001060 // Get BootMode as BootSourceOverrideTarget is constructed
1061 // from both BootSource and BootMode
1062 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001063 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301064}
1065
1066/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001067 * @brief This functions abstracts all the logic behind getting a
1068 * "BootSourceOverrideEnabled" property from an overall boot override enable
1069 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301070 *
1071 * @param[in] aResp Shared pointer for generating response message.
1072 *
1073 * @return None.
1074 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301075
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001076inline void
1077 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1078 const bool bootOverrideEnableSetting)
1079{
1080 if (!bootOverrideEnableSetting)
1081 {
1082 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1083 return;
1084 }
1085
1086 // If boot source override is enabled, we need to check 'one_time'
1087 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001088 sdbusplus::asio::getProperty<bool>(
1089 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1090 "/xyz/openbmc_project/control/host0/boot/one_time",
1091 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001092 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001093 if (ec)
1094 {
1095 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1096 messages::internalError(aResp->res);
1097 return;
1098 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301099
Ed Tanous002d39b2022-05-31 08:59:27 -07001100 if (oneTimeSetting)
1101 {
1102 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1103 }
1104 else
1105 {
1106 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1107 "Continuous";
1108 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001109 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301110}
1111
1112/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001113 * @brief Retrieves boot override enable over DBUS
1114 *
1115 * @param[in] aResp Shared pointer for generating response message.
1116 *
1117 * @return None.
1118 */
1119
1120inline void
1121 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1122{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001123 sdbusplus::asio::getProperty<bool>(
1124 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1125 "/xyz/openbmc_project/control/host0/boot",
1126 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001127 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001128 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001129 if (ec)
1130 {
1131 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001132 if (ec.value() == boost::asio::error::host_unreachable)
1133 {
1134 return;
1135 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001136 messages::internalError(aResp->res);
1137 return;
1138 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001139
Ed Tanous002d39b2022-05-31 08:59:27 -07001140 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001141 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001142}
1143
1144/**
1145 * @brief Retrieves boot source override properties
1146 *
1147 * @param[in] aResp Shared pointer for generating response message.
1148 *
1149 * @return None.
1150 */
1151inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1152{
1153 BMCWEB_LOG_DEBUG << "Get boot information.";
1154
1155 getBootOverrideSource(aResp);
1156 getBootOverrideType(aResp);
1157 getBootOverrideEnable(aResp);
1158}
1159
1160/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001161 * @brief Retrieves the Last Reset Time
1162 *
1163 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1164 * and power off. Even though this is the "system" Redfish object look at the
1165 * chassis D-Bus interface for the LastStateChangeTime since this has the
1166 * last power operation time.
1167 *
1168 * @param[in] aResp Shared pointer for generating response message.
1169 *
1170 * @return None.
1171 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001172inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001173{
1174 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1175
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001176 sdbusplus::asio::getProperty<uint64_t>(
1177 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1178 "/xyz/openbmc_project/state/chassis0",
1179 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001180 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001181 if (ec)
1182 {
1183 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1184 return;
1185 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001186
Ed Tanous002d39b2022-05-31 08:59:27 -07001187 // LastStateChangeTime is epoch time, in milliseconds
1188 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1189 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001190
Ed Tanous002d39b2022-05-31 08:59:27 -07001191 // Convert to ISO 8601 standard
1192 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001193 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001194 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001195}
1196
1197/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001198 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1199 *
1200 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1201 * corresponding property "AttemptsLeft" that keeps track of the amount of
1202 * automatic retry attempts left are hosted in phosphor-state-manager through
1203 * dbus.
1204 *
1205 * @param[in] aResp Shared pointer for generating response message.
1206 *
1207 * @return None.
1208 */
1209inline void
1210 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1211{
1212 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1213
1214 sdbusplus::asio::getAllProperties(
1215 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1216 "/xyz/openbmc_project/state/host0",
1217 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1218 [aResp{aResp}](const boost::system::error_code& ec,
1219 const dbus::utility::DBusPropertiesMap& propertiesList) {
1220 if (ec)
1221 {
1222 if (ec.value() != EBADR)
1223 {
1224 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1225 messages::internalError(aResp->res);
1226 }
1227 return;
1228 }
1229
1230 const uint32_t* attemptsLeft = nullptr;
1231 const uint32_t* retryAttempts = nullptr;
1232
1233 const bool success = sdbusplus::unpackPropertiesNoThrow(
1234 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1235 attemptsLeft, "RetryAttempts", retryAttempts);
1236
1237 if (!success)
1238 {
1239 messages::internalError(aResp->res);
1240 return;
1241 }
1242
1243 if (attemptsLeft != nullptr)
1244 {
1245 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1246 *attemptsLeft;
1247 }
1248
1249 if (retryAttempts != nullptr)
1250 {
1251 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1252 *retryAttempts;
1253 }
1254 });
1255}
1256
1257/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001258 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1259 *
1260 * @param[in] aResp Shared pointer for generating response message.
1261 *
1262 * @return None.
1263 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001264inline void
1265 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001266{
1267 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1268
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001269 sdbusplus::asio::getProperty<bool>(
1270 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1271 "/xyz/openbmc_project/control/host0/auto_reboot",
1272 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001273 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001274 if (ec)
1275 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001276 if (ec.value() != EBADR)
1277 {
1278 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1279 messages::internalError(aResp->res);
1280 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001281 return;
1282 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001283
Ed Tanous002d39b2022-05-31 08:59:27 -07001284 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1285 if (autoRebootEnabled)
1286 {
1287 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1288 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001289 }
1290 else
1291 {
1292 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1293 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001294 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001295
Ed Tanous002d39b2022-05-31 08:59:27 -07001296 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1297 // and RetryAttempts. OpenBMC only supports Disabled and
1298 // RetryAttempts.
1299 aResp->res.jsonValue["Boot"]
1300 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1301 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001302 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001303}
1304
1305/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001306 * @brief Sets RetryAttempts
1307 *
1308 * @param[in] aResp Shared pointer for generating response message.
1309 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1310 *
1311 *@return None.
1312 */
1313
1314inline void
1315 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1316 const uint32_t retryAttempts)
1317{
1318 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1319 crow::connections::systemBus->async_method_call(
1320 [aResp](const boost::system::error_code& ec) {
1321 if (ec)
1322 {
1323 BMCWEB_LOG_ERROR
1324 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1325 messages::internalError(aResp->res);
1326 return;
1327 }
1328 },
1329 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1330 "org.freedesktop.DBus.Properties", "Set",
1331 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1332 std::variant<uint32_t>(retryAttempts));
1333}
1334
1335/**
George Liuc6a620f2020-04-10 17:18:11 +08001336 * @brief Retrieves power restore policy over DBUS.
1337 *
1338 * @param[in] aResp Shared pointer for generating response message.
1339 *
1340 * @return None.
1341 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001342inline void
1343 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001344{
1345 BMCWEB_LOG_DEBUG << "Get power restore policy";
1346
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001347 sdbusplus::asio::getProperty<std::string>(
1348 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1349 "/xyz/openbmc_project/control/host0/power_restore_policy",
1350 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001351 [aResp](const boost::system::error_code& ec,
1352 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001353 if (ec)
1354 {
1355 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1356 return;
1357 }
George Liuc6a620f2020-04-10 17:18:11 +08001358
Ed Tanous002d39b2022-05-31 08:59:27 -07001359 const boost::container::flat_map<std::string, std::string> policyMaps = {
1360 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1361 "AlwaysOn"},
1362 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1363 "AlwaysOff"},
1364 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1365 "LastState"},
1366 // Return `AlwaysOff` when power restore policy set to "None"
1367 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1368 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001369
Ed Tanous002d39b2022-05-31 08:59:27 -07001370 auto policyMapsIt = policyMaps.find(policy);
1371 if (policyMapsIt == policyMaps.end())
1372 {
1373 messages::internalError(aResp->res);
1374 return;
1375 }
George Liuc6a620f2020-04-10 17:18:11 +08001376
Ed Tanous002d39b2022-05-31 08:59:27 -07001377 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001378 });
George Liuc6a620f2020-04-10 17:18:11 +08001379}
1380
1381/**
Ali Ahmed19817712021-06-29 17:01:52 -05001382 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1383 * TPM is required for booting the host.
1384 *
1385 * @param[in] aResp Shared pointer for generating response message.
1386 *
1387 * @return None.
1388 */
1389inline void getTrustedModuleRequiredToBoot(
1390 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1391{
1392 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001393 constexpr std::array<std::string_view, 1> interfaces = {
1394 "xyz.openbmc_project.Control.TPM.Policy"};
1395 dbus::utility::getSubTree(
1396 "/", 0, interfaces,
1397 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001398 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001399 if (ec)
1400 {
1401 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1402 << ec;
1403 // This is an optional D-Bus object so just return if
1404 // error occurs
1405 return;
1406 }
1407 if (subtree.empty())
1408 {
1409 // As noted above, this is an optional interface so just return
1410 // if there is no instance found
1411 return;
1412 }
1413
1414 /* When there is more than one TPMEnable object... */
1415 if (subtree.size() > 1)
1416 {
1417 BMCWEB_LOG_DEBUG
1418 << "DBUS response has more than 1 TPM Enable object:"
1419 << subtree.size();
1420 // Throw an internal Error and return
1421 messages::internalError(aResp->res);
1422 return;
1423 }
1424
1425 // Make sure the Dbus response map has a service and objectPath
1426 // field
1427 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1428 {
1429 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1430 messages::internalError(aResp->res);
1431 return;
1432 }
1433
1434 const std::string& path = subtree[0].first;
1435 const std::string& serv = subtree[0].second.begin()->first;
1436
1437 // Valid TPM Enable object found, now reading the current value
1438 sdbusplus::asio::getProperty<bool>(
1439 *crow::connections::systemBus, serv, path,
1440 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001441 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001442 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001443 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001444 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001445 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001446 messages::internalError(aResp->res);
1447 return;
1448 }
1449
Ed Tanous002d39b2022-05-31 08:59:27 -07001450 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001451 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001452 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1453 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001454 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001455 else
1456 {
1457 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1458 "Disabled";
1459 }
1460 });
George Liue99073f2022-12-09 11:06:16 +08001461 });
Ali Ahmed19817712021-06-29 17:01:52 -05001462}
1463
1464/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001465 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1466 * TPM is required for booting the host.
1467 *
1468 * @param[in] aResp Shared pointer for generating response message.
1469 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1470 *
1471 * @return None.
1472 */
1473inline void setTrustedModuleRequiredToBoot(
1474 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1475{
1476 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001477 constexpr std::array<std::string_view, 1> interfaces = {
1478 "xyz.openbmc_project.Control.TPM.Policy"};
1479 dbus::utility::getSubTree(
1480 "/", 0, interfaces,
1481 [aResp,
1482 tpmRequired](const boost::system::error_code& ec,
1483 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001484 if (ec)
1485 {
1486 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1487 << ec;
1488 messages::internalError(aResp->res);
1489 return;
1490 }
1491 if (subtree.empty())
1492 {
1493 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1494 "TrustedModuleRequiredToBoot");
1495 return;
1496 }
1497
1498 /* When there is more than one TPMEnable object... */
1499 if (subtree.size() > 1)
1500 {
1501 BMCWEB_LOG_DEBUG
1502 << "DBUS response has more than 1 TPM Enable object:"
1503 << subtree.size();
1504 // Throw an internal Error and return
1505 messages::internalError(aResp->res);
1506 return;
1507 }
1508
1509 // Make sure the Dbus response map has a service and objectPath
1510 // field
1511 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1512 {
1513 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1514 messages::internalError(aResp->res);
1515 return;
1516 }
1517
1518 const std::string& path = subtree[0].first;
1519 const std::string& serv = subtree[0].second.begin()->first;
1520
1521 if (serv.empty())
1522 {
1523 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1524 messages::internalError(aResp->res);
1525 return;
1526 }
1527
1528 // Valid TPM Enable object found, now setting the value
1529 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001530 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001531 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001532 {
1533 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001534 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001535 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001536 messages::internalError(aResp->res);
1537 return;
1538 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001539 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1540 },
1541 serv, path, "org.freedesktop.DBus.Properties", "Set",
1542 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1543 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001544 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001545}
1546
1547/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301548 * @brief Sets boot properties into DBUS object(s).
1549 *
1550 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001551 * @param[in] bootType The boot type to set.
1552 * @return Integer error code.
1553 */
1554inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001555 const std::optional<std::string>& bootType)
1556{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001557 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001558
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001559 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001560 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001561 return;
1562 }
1563
1564 // Source target specified
1565 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1566 // Figure out which DBUS interface and property to use
1567 if (*bootType == "Legacy")
1568 {
1569 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1570 }
1571 else if (*bootType == "UEFI")
1572 {
1573 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1574 }
1575 else
1576 {
1577 BMCWEB_LOG_DEBUG << "Invalid property value for "
1578 "BootSourceOverrideMode: "
1579 << *bootType;
1580 messages::propertyValueNotInList(aResp->res, *bootType,
1581 "BootSourceOverrideMode");
1582 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001583 }
1584
1585 // Act on validated parameters
1586 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1587
1588 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001589 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001590 if (ec)
1591 {
1592 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1593 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001594 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001595 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001596 return;
1597 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001598 messages::internalError(aResp->res);
1599 return;
1600 }
1601 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001602 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001603 "xyz.openbmc_project.Settings",
1604 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001605 "org.freedesktop.DBus.Properties", "Set",
1606 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001607 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001608}
1609
1610/**
1611 * @brief Sets boot properties into DBUS object(s).
1612 *
1613 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001614 * @param[in] bootType The boot type to set.
1615 * @return Integer error code.
1616 */
1617inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1618 const std::optional<std::string>& bootEnable)
1619{
1620 if (!bootEnable)
1621 {
1622 return;
1623 }
1624 // Source target specified
1625 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1626
1627 bool bootOverrideEnable = false;
1628 bool bootOverridePersistent = false;
1629 // Figure out which DBUS interface and property to use
1630 if (*bootEnable == "Disabled")
1631 {
1632 bootOverrideEnable = false;
1633 }
1634 else if (*bootEnable == "Once")
1635 {
1636 bootOverrideEnable = true;
1637 bootOverridePersistent = false;
1638 }
1639 else if (*bootEnable == "Continuous")
1640 {
1641 bootOverrideEnable = true;
1642 bootOverridePersistent = true;
1643 }
1644 else
1645 {
George Liu0fda0f12021-11-16 10:06:17 +08001646 BMCWEB_LOG_DEBUG
1647 << "Invalid property value for BootSourceOverrideEnabled: "
1648 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001649 messages::propertyValueNotInList(aResp->res, *bootEnable,
1650 "BootSourceOverrideEnabled");
1651 return;
1652 }
1653
1654 // Act on validated parameters
1655 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1656
1657 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001658 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001659 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001660 {
Ed Tanous8a592812022-06-04 09:06:59 -07001661 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001662 messages::internalError(aResp->res);
1663 return;
1664 }
1665 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001666 },
1667 "xyz.openbmc_project.Settings",
1668 "/xyz/openbmc_project/control/host0/boot",
1669 "org.freedesktop.DBus.Properties", "Set",
1670 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001671 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001672
1673 if (!bootOverrideEnable)
1674 {
1675 return;
1676 }
1677
1678 // In case boot override is enabled we need to set correct value for the
1679 // 'one_time' enable DBus interface
1680 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1681 << bootOverridePersistent;
1682
1683 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001684 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001685 if (ec)
1686 {
1687 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1688 messages::internalError(aResp->res);
1689 return;
1690 }
1691 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001692 },
1693 "xyz.openbmc_project.Settings",
1694 "/xyz/openbmc_project/control/host0/boot/one_time",
1695 "org.freedesktop.DBus.Properties", "Set",
1696 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001697 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001698}
1699
1700/**
1701 * @brief Sets boot properties into DBUS object(s).
1702 *
1703 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301704 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301705 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001706 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301707 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001708inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001709 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301710{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001711 std::string bootSourceStr;
1712 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001713
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001714 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301715 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001716 return;
1717 }
1718
1719 // Source target specified
1720 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1721 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001722 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1723 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001724 {
1725 BMCWEB_LOG_DEBUG
1726 << "Invalid property value for BootSourceOverrideTarget: "
1727 << *bootSource;
1728 messages::propertyValueNotInList(aResp->res, *bootSource,
1729 "BootSourceTargetOverride");
1730 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001731 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301732
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001733 // Act on validated parameters
1734 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1735 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001736
1737 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001738 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001739 if (ec)
1740 {
1741 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1742 messages::internalError(aResp->res);
1743 return;
1744 }
1745 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001746 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001747 "xyz.openbmc_project.Settings",
1748 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001749 "org.freedesktop.DBus.Properties", "Set",
1750 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001751 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001752
1753 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001754 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001755 if (ec)
1756 {
1757 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1758 messages::internalError(aResp->res);
1759 return;
1760 }
1761 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001762 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001763 "xyz.openbmc_project.Settings",
1764 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001765 "org.freedesktop.DBus.Properties", "Set",
1766 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001767 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001768}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001769
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001770/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001771 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301772 *
1773 * @param[in] aResp Shared pointer for generating response message.
1774 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001775 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301776 * @param[in] bootEnable The boot override enable from incoming RF request.
1777 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001778 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301779 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001780
1781inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1782 const std::optional<std::string>& bootSource,
1783 const std::optional<std::string>& bootType,
1784 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301785{
1786 BMCWEB_LOG_DEBUG << "Set boot information.";
1787
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001788 setBootModeOrSource(aResp, bootSource);
1789 setBootType(aResp, bootType);
1790 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301791}
1792
George Liuc6a620f2020-04-10 17:18:11 +08001793/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001794 * @brief Sets AssetTag
1795 *
1796 * @param[in] aResp Shared pointer for generating response message.
1797 * @param[in] assetTag "AssetTag" from request.
1798 *
1799 * @return None.
1800 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001801inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001802 const std::string& assetTag)
1803{
George Liue99073f2022-12-09 11:06:16 +08001804 constexpr std::array<std::string_view, 1> interfaces = {
1805 "xyz.openbmc_project.Inventory.Item.System"};
1806 dbus::utility::getSubTree(
1807 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001808 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001809 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001810 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001811 if (ec)
1812 {
1813 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1814 messages::internalError(aResp->res);
1815 return;
1816 }
1817 if (subtree.empty())
1818 {
1819 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1820 messages::internalError(aResp->res);
1821 return;
1822 }
1823 // Assume only 1 system D-Bus object
1824 // Throw an error if there is more than 1
1825 if (subtree.size() > 1)
1826 {
1827 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1828 messages::internalError(aResp->res);
1829 return;
1830 }
1831 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1832 {
1833 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1834 messages::internalError(aResp->res);
1835 return;
1836 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001837
Ed Tanous002d39b2022-05-31 08:59:27 -07001838 const std::string& path = subtree[0].first;
1839 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001840
Ed Tanous002d39b2022-05-31 08:59:27 -07001841 if (service.empty())
1842 {
1843 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1844 messages::internalError(aResp->res);
1845 return;
1846 }
1847
1848 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001849 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001850 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001851 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001852 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1853 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001854 messages::internalError(aResp->res);
1855 return;
1856 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001857 },
1858 service, path, "org.freedesktop.DBus.Properties", "Set",
1859 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1860 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001861 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001862}
1863
1864/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001865 * @brief Sets automaticRetry (Auto Reboot)
1866 *
1867 * @param[in] aResp Shared pointer for generating response message.
1868 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1869 *
1870 * @return None.
1871 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001872inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001873 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001874{
1875 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1876
1877 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001878 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001879
1880 if (automaticRetryConfig == "Disabled")
1881 {
1882 autoRebootEnabled = false;
1883 }
1884 else if (automaticRetryConfig == "RetryAttempts")
1885 {
1886 autoRebootEnabled = true;
1887 }
1888 else
1889 {
George Liu0fda0f12021-11-16 10:06:17 +08001890 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001891 << automaticRetryConfig;
1892 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1893 "AutomaticRetryConfig");
1894 return;
1895 }
1896
1897 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001898 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001899 if (ec)
1900 {
1901 messages::internalError(aResp->res);
1902 return;
1903 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001904 },
1905 "xyz.openbmc_project.Settings",
1906 "/xyz/openbmc_project/control/host0/auto_reboot",
1907 "org.freedesktop.DBus.Properties", "Set",
1908 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001909 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001910}
1911
1912/**
George Liuc6a620f2020-04-10 17:18:11 +08001913 * @brief Sets power restore policy properties.
1914 *
1915 * @param[in] aResp Shared pointer for generating response message.
1916 * @param[in] policy power restore policy properties from request.
1917 *
1918 * @return None.
1919 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001920inline void
1921 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1922 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001923{
1924 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1925
1926 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001927 {"AlwaysOn",
1928 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1929 {"AlwaysOff",
1930 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1931 {"LastState",
1932 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001933
1934 std::string powerRestorPolicy;
1935
Gunnar Mills4e69c902021-01-05 19:50:11 -06001936 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001937 if (policyMapsIt == policyMaps.end())
1938 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001939 messages::propertyValueNotInList(aResp->res, policy,
1940 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001941 return;
1942 }
1943
1944 powerRestorPolicy = policyMapsIt->second;
1945
1946 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001947 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001948 if (ec)
1949 {
1950 messages::internalError(aResp->res);
1951 return;
1952 }
George Liuc6a620f2020-04-10 17:18:11 +08001953 },
1954 "xyz.openbmc_project.Settings",
1955 "/xyz/openbmc_project/control/host0/power_restore_policy",
1956 "org.freedesktop.DBus.Properties", "Set",
1957 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001958 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001959}
1960
AppaRao Pulia6349912019-10-18 17:16:08 +05301961#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1962/**
1963 * @brief Retrieves provisioning status
1964 *
1965 * @param[in] aResp Shared pointer for completing asynchronous calls.
1966 *
1967 * @return None.
1968 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001969inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301970{
1971 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001972 sdbusplus::asio::getAllProperties(
1973 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1974 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001975 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001976 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001977 nlohmann::json& oemPFR =
1978 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1979 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1980 "#OemComputerSystem.OpenBmc";
1981 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001982
Ed Tanous002d39b2022-05-31 08:59:27 -07001983 if (ec)
1984 {
1985 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1986 // not an error, don't have to have the interface
1987 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1988 return;
1989 }
1990
1991 const bool* provState = nullptr;
1992 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001993
1994 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001995 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1996 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001997
1998 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001999 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002000 messages::internalError(aResp->res);
2001 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002002 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302003
Ed Tanous002d39b2022-05-31 08:59:27 -07002004 if ((provState == nullptr) || (lockState == nullptr))
2005 {
2006 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
2007 messages::internalError(aResp->res);
2008 return;
2009 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302010
Ed Tanous002d39b2022-05-31 08:59:27 -07002011 if (*provState == true)
2012 {
2013 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05302014 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002015 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302016 }
2017 else
2018 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002019 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05302020 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002021 }
2022 else
2023 {
2024 oemPFR["ProvisioningStatus"] = "NotProvisioned";
2025 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002026 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302027}
2028#endif
2029
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302030/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002031 * @brief Translate the PowerMode to a response message.
2032 *
2033 * @param[in] aResp Shared pointer for generating response message.
2034 * @param[in] modeValue PowerMode value to be translated
2035 *
2036 * @return None.
2037 */
2038inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2039 const std::string& modeValue)
2040{
George Liu0fda0f12021-11-16 10:06:17 +08002041 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002042 {
2043 aResp->res.jsonValue["PowerMode"] = "Static";
2044 }
George Liu0fda0f12021-11-16 10:06:17 +08002045 else if (
2046 modeValue ==
2047 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002048 {
2049 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2050 }
George Liu0fda0f12021-11-16 10:06:17 +08002051 else if (modeValue ==
2052 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002053 {
2054 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2055 }
George Liu0fda0f12021-11-16 10:06:17 +08002056 else if (modeValue ==
2057 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002058 {
2059 aResp->res.jsonValue["PowerMode"] = "OEM";
2060 }
2061 else
2062 {
2063 // Any other values would be invalid
2064 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2065 messages::internalError(aResp->res);
2066 }
2067}
2068
2069/**
2070 * @brief Retrieves system power mode
2071 *
2072 * @param[in] aResp Shared pointer for generating response message.
2073 *
2074 * @return None.
2075 */
2076inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2077{
2078 BMCWEB_LOG_DEBUG << "Get power mode.";
2079
2080 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002081 constexpr std::array<std::string_view, 1> interfaces = {
2082 "xyz.openbmc_project.Control.Power.Mode"};
2083 dbus::utility::getSubTree(
2084 "/", 0, interfaces,
2085 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002086 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002087 if (ec)
2088 {
2089 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2090 << ec;
2091 // This is an optional D-Bus object so just return if
2092 // error occurs
2093 return;
2094 }
2095 if (subtree.empty())
2096 {
2097 // As noted above, this is an optional interface so just return
2098 // if there is no instance found
2099 return;
2100 }
2101 if (subtree.size() > 1)
2102 {
2103 // More then one PowerMode object is not supported and is an
2104 // error
2105 BMCWEB_LOG_DEBUG
2106 << "Found more than 1 system D-Bus Power.Mode objects: "
2107 << subtree.size();
2108 messages::internalError(aResp->res);
2109 return;
2110 }
2111 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2112 {
2113 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2114 messages::internalError(aResp->res);
2115 return;
2116 }
2117 const std::string& path = subtree[0].first;
2118 const std::string& service = subtree[0].second.begin()->first;
2119 if (service.empty())
2120 {
2121 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2122 messages::internalError(aResp->res);
2123 return;
2124 }
2125 // Valid Power Mode object found, now read the current value
2126 sdbusplus::asio::getProperty<std::string>(
2127 *crow::connections::systemBus, service, path,
2128 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002129 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002130 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002131 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002132 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002133 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002134 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002135 messages::internalError(aResp->res);
2136 return;
2137 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002138
Ed Tanous002d39b2022-05-31 08:59:27 -07002139 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2140 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002141
Ed Tanous002d39b2022-05-31 08:59:27 -07002142 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2143 translatePowerMode(aResp, pmode);
2144 });
George Liue99073f2022-12-09 11:06:16 +08002145 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002146}
2147
2148/**
2149 * @brief Validate the specified mode is valid and return the PowerMode
2150 * name associated with that string
2151 *
2152 * @param[in] aResp Shared pointer for generating response message.
2153 * @param[in] modeString String representing the desired PowerMode
2154 *
2155 * @return PowerMode value or empty string if mode is not valid
2156 */
2157inline std::string
2158 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2159 const std::string& modeString)
2160{
2161 std::string mode;
2162
2163 if (modeString == "Static")
2164 {
2165 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2166 }
2167 else if (modeString == "MaximumPerformance")
2168 {
George Liu0fda0f12021-11-16 10:06:17 +08002169 mode =
2170 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002171 }
2172 else if (modeString == "PowerSaving")
2173 {
2174 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2175 }
2176 else
2177 {
2178 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2179 }
2180 return mode;
2181}
2182
2183/**
2184 * @brief Sets system power mode.
2185 *
2186 * @param[in] aResp Shared pointer for generating response message.
2187 * @param[in] pmode System power mode from request.
2188 *
2189 * @return None.
2190 */
2191inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2192 const std::string& pmode)
2193{
2194 BMCWEB_LOG_DEBUG << "Set power mode.";
2195
2196 std::string powerMode = validatePowerMode(aResp, pmode);
2197 if (powerMode.empty())
2198 {
2199 return;
2200 }
2201
2202 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002203 constexpr std::array<std::string_view, 1> interfaces = {
2204 "xyz.openbmc_project.Control.Power.Mode"};
2205 dbus::utility::getSubTree(
2206 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002207 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002208 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002209 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002210 if (ec)
2211 {
2212 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2213 << ec;
2214 // This is an optional D-Bus object, but user attempted to patch
2215 messages::internalError(aResp->res);
2216 return;
2217 }
2218 if (subtree.empty())
2219 {
2220 // This is an optional D-Bus object, but user attempted to patch
2221 messages::resourceNotFound(aResp->res, "ComputerSystem",
2222 "PowerMode");
2223 return;
2224 }
2225 if (subtree.size() > 1)
2226 {
2227 // More then one PowerMode object is not supported and is an
2228 // error
2229 BMCWEB_LOG_DEBUG
2230 << "Found more than 1 system D-Bus Power.Mode objects: "
2231 << subtree.size();
2232 messages::internalError(aResp->res);
2233 return;
2234 }
2235 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2236 {
2237 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2238 messages::internalError(aResp->res);
2239 return;
2240 }
2241 const std::string& path = subtree[0].first;
2242 const std::string& service = subtree[0].second.begin()->first;
2243 if (service.empty())
2244 {
2245 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2246 messages::internalError(aResp->res);
2247 return;
2248 }
2249
2250 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2251 << path;
2252
2253 // Set the Power Mode property
2254 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002255 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002256 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002257 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002258 messages::internalError(aResp->res);
2259 return;
2260 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002261 },
2262 service, path, "org.freedesktop.DBus.Properties", "Set",
2263 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2264 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002265 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002266}
2267
2268/**
Yong Li51709ff2019-09-30 14:13:04 +08002269 * @brief Translates watchdog timeout action DBUS property value to redfish.
2270 *
2271 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2272 *
2273 * @return Returns as a string, the timeout action in Redfish terms. If
2274 * translation cannot be done, returns an empty string.
2275 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002276inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002277{
2278 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2279 {
2280 return "None";
2281 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002282 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002283 {
2284 return "ResetSystem";
2285 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002286 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002287 {
2288 return "PowerDown";
2289 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002290 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002291 {
2292 return "PowerCycle";
2293 }
2294
2295 return "";
2296}
2297
2298/**
Yong Lic45f0082019-10-10 14:19:01 +08002299 *@brief Translates timeout action from Redfish to DBUS property value.
2300 *
2301 *@param[in] rfAction The timeout action in Redfish.
2302 *
2303 *@return Returns as a string, the time_out action as expected by DBUS.
2304 *If translation cannot be done, returns an empty string.
2305 */
2306
Ed Tanous23a21a12020-07-25 04:45:05 +00002307inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002308{
2309 if (rfAction == "None")
2310 {
2311 return "xyz.openbmc_project.State.Watchdog.Action.None";
2312 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002313 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002314 {
2315 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2316 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002317 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002318 {
2319 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2320 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002321 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002322 {
2323 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2324 }
2325
2326 return "";
2327}
2328
2329/**
Yong Li51709ff2019-09-30 14:13:04 +08002330 * @brief Retrieves host watchdog timer properties over DBUS
2331 *
2332 * @param[in] aResp Shared pointer for completing asynchronous calls.
2333 *
2334 * @return None.
2335 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002336inline void
2337 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002338{
2339 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002340 sdbusplus::asio::getAllProperties(
2341 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2342 "/xyz/openbmc_project/watchdog/host0",
2343 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002344 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002345 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002346 if (ec)
2347 {
2348 // watchdog service is stopped
2349 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2350 return;
2351 }
2352
2353 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2354
2355 nlohmann::json& hostWatchdogTimer =
2356 aResp->res.jsonValue["HostWatchdogTimer"];
2357
2358 // watchdog service is running/enabled
2359 hostWatchdogTimer["Status"]["State"] = "Enabled";
2360
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002361 const bool* enabled = nullptr;
2362 const std::string* expireAction = nullptr;
2363
2364 const bool success = sdbusplus::unpackPropertiesNoThrow(
2365 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2366 "ExpireAction", expireAction);
2367
2368 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002369 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002370 messages::internalError(aResp->res);
2371 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002372 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002373
2374 if (enabled != nullptr)
2375 {
2376 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2377 }
2378
2379 if (expireAction != nullptr)
2380 {
2381 std::string action = dbusToRfWatchdogAction(*expireAction);
2382 if (action.empty())
2383 {
2384 messages::internalError(aResp->res);
2385 return;
2386 }
2387 hostWatchdogTimer["TimeoutAction"] = action;
2388 }
2389 });
Yong Li51709ff2019-09-30 14:13:04 +08002390}
2391
2392/**
Yong Lic45f0082019-10-10 14:19:01 +08002393 * @brief Sets Host WatchDog Timer properties.
2394 *
2395 * @param[in] aResp Shared pointer for generating response message.
2396 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2397 * RF request.
2398 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2399 *
2400 * @return None.
2401 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002402inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002403 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002404 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002405{
2406 BMCWEB_LOG_DEBUG << "Set host watchdog";
2407
2408 if (wdtTimeOutAction)
2409 {
2410 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2411 // check if TimeOut Action is Valid
2412 if (wdtTimeOutActStr.empty())
2413 {
2414 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2415 << *wdtTimeOutAction;
2416 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2417 "TimeoutAction");
2418 return;
2419 }
2420
2421 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002422 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002423 if (ec)
2424 {
2425 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2426 messages::internalError(aResp->res);
2427 return;
2428 }
Yong Lic45f0082019-10-10 14:19:01 +08002429 },
2430 "xyz.openbmc_project.Watchdog",
2431 "/xyz/openbmc_project/watchdog/host0",
2432 "org.freedesktop.DBus.Properties", "Set",
2433 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002434 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002435 }
2436
2437 if (wdtEnable)
2438 {
2439 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002440 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002441 if (ec)
2442 {
2443 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2444 messages::internalError(aResp->res);
2445 return;
2446 }
Yong Lic45f0082019-10-10 14:19:01 +08002447 },
2448 "xyz.openbmc_project.Watchdog",
2449 "/xyz/openbmc_project/watchdog/host0",
2450 "org.freedesktop.DBus.Properties", "Set",
2451 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002452 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002453 }
2454}
2455
Chris Cain37bbf982021-09-20 10:53:09 -05002456/**
2457 * @brief Parse the Idle Power Saver properties into json
2458 *
2459 * @param[in] aResp Shared pointer for completing asynchronous calls.
2460 * @param[in] properties IPS property data from DBus.
2461 *
2462 * @return true if successful
2463 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002464inline bool
2465 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2466 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002467{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002468 const bool* enabled = nullptr;
2469 const uint8_t* enterUtilizationPercent = nullptr;
2470 const uint64_t* enterDwellTime = nullptr;
2471 const uint8_t* exitUtilizationPercent = nullptr;
2472 const uint64_t* exitDwellTime = nullptr;
2473
2474 const bool success = sdbusplus::unpackPropertiesNoThrow(
2475 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002476 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2477 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2478 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002479
2480 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002481 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002482 return false;
2483 }
2484
2485 if (enabled != nullptr)
2486 {
2487 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2488 }
2489
2490 if (enterUtilizationPercent != nullptr)
2491 {
2492 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2493 *enterUtilizationPercent;
2494 }
2495
2496 if (enterDwellTime != nullptr)
2497 {
2498 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2499 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2500 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2501 .count();
2502 }
2503
2504 if (exitUtilizationPercent != nullptr)
2505 {
2506 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2507 *exitUtilizationPercent;
2508 }
2509
2510 if (exitDwellTime != nullptr)
2511 {
2512 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2513 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2514 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2515 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002516 }
2517
2518 return true;
2519}
2520
2521/**
2522 * @brief Retrieves host watchdog timer properties over DBUS
2523 *
2524 * @param[in] aResp Shared pointer for completing asynchronous calls.
2525 *
2526 * @return None.
2527 */
2528inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2529{
2530 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2531
2532 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002533 constexpr std::array<std::string_view, 1> interfaces = {
2534 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2535 dbus::utility::getSubTree(
2536 "/", 0, interfaces,
2537 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002538 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002539 if (ec)
2540 {
2541 BMCWEB_LOG_DEBUG
2542 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2543 << ec;
2544 messages::internalError(aResp->res);
2545 return;
2546 }
2547 if (subtree.empty())
2548 {
2549 // This is an optional interface so just return
2550 // if there is no instance found
2551 BMCWEB_LOG_DEBUG << "No instances found";
2552 return;
2553 }
2554 if (subtree.size() > 1)
2555 {
2556 // More then one PowerIdlePowerSaver object is not supported and
2557 // is an error
2558 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2559 "Power.IdlePowerSaver objects: "
2560 << subtree.size();
2561 messages::internalError(aResp->res);
2562 return;
2563 }
2564 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2565 {
2566 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2567 messages::internalError(aResp->res);
2568 return;
2569 }
2570 const std::string& path = subtree[0].first;
2571 const std::string& service = subtree[0].second.begin()->first;
2572 if (service.empty())
2573 {
2574 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2575 messages::internalError(aResp->res);
2576 return;
2577 }
2578
2579 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002580 sdbusplus::asio::getAllProperties(
2581 *crow::connections::systemBus, service, path,
2582 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002583 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002584 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002585 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002586 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002587 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002588 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002589 messages::internalError(aResp->res);
2590 return;
2591 }
2592
Ed Tanous002d39b2022-05-31 08:59:27 -07002593 if (!parseIpsProperties(aResp, properties))
2594 {
2595 messages::internalError(aResp->res);
2596 return;
2597 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002598 });
George Liue99073f2022-12-09 11:06:16 +08002599 });
Chris Cain37bbf982021-09-20 10:53:09 -05002600
2601 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2602}
2603
2604/**
2605 * @brief Sets Idle Power Saver properties.
2606 *
2607 * @param[in] aResp Shared pointer for generating response message.
2608 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2609 * RF request.
2610 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2611 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2612 * before entering idle state.
2613 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2614 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2615 * before exiting idle state
2616 *
2617 * @return None.
2618 */
2619inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2620 const std::optional<bool> ipsEnable,
2621 const std::optional<uint8_t> ipsEnterUtil,
2622 const std::optional<uint64_t> ipsEnterTime,
2623 const std::optional<uint8_t> ipsExitUtil,
2624 const std::optional<uint64_t> ipsExitTime)
2625{
2626 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2627
2628 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002629 constexpr std::array<std::string_view, 1> interfaces = {
2630 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2631 dbus::utility::getSubTree(
2632 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002633 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002634 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002635 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002636 if (ec)
2637 {
2638 BMCWEB_LOG_DEBUG
2639 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2640 << ec;
2641 messages::internalError(aResp->res);
2642 return;
2643 }
2644 if (subtree.empty())
2645 {
2646 // This is an optional D-Bus object, but user attempted to patch
2647 messages::resourceNotFound(aResp->res, "ComputerSystem",
2648 "IdlePowerSaver");
2649 return;
2650 }
2651 if (subtree.size() > 1)
2652 {
2653 // More then one PowerIdlePowerSaver object is not supported and
2654 // is an error
2655 BMCWEB_LOG_DEBUG
2656 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2657 << subtree.size();
2658 messages::internalError(aResp->res);
2659 return;
2660 }
2661 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2662 {
2663 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2664 messages::internalError(aResp->res);
2665 return;
2666 }
2667 const std::string& path = subtree[0].first;
2668 const std::string& service = subtree[0].second.begin()->first;
2669 if (service.empty())
2670 {
2671 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2672 messages::internalError(aResp->res);
2673 return;
2674 }
Chris Cain37bbf982021-09-20 10:53:09 -05002675
Ed Tanous002d39b2022-05-31 08:59:27 -07002676 // Valid Power IdlePowerSaver object found, now set any values that
2677 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002678
Ed Tanous002d39b2022-05-31 08:59:27 -07002679 if (ipsEnable)
2680 {
2681 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002682 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002683 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002684 {
Ed Tanous8a592812022-06-04 09:06:59 -07002685 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002686 messages::internalError(aResp->res);
2687 return;
2688 }
2689 },
2690 service, path, "org.freedesktop.DBus.Properties", "Set",
2691 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2692 dbus::utility::DbusVariantType(*ipsEnable));
2693 }
2694 if (ipsEnterUtil)
2695 {
2696 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002697 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002698 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002699 {
Ed Tanous8a592812022-06-04 09:06:59 -07002700 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002701 messages::internalError(aResp->res);
2702 return;
2703 }
2704 },
2705 service, path, "org.freedesktop.DBus.Properties", "Set",
2706 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2707 "EnterUtilizationPercent",
2708 dbus::utility::DbusVariantType(*ipsEnterUtil));
2709 }
2710 if (ipsEnterTime)
2711 {
2712 // Convert from seconds into milliseconds for DBus
2713 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2714 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002715 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002716 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002717 {
Ed Tanous8a592812022-06-04 09:06:59 -07002718 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002719 messages::internalError(aResp->res);
2720 return;
2721 }
2722 },
2723 service, path, "org.freedesktop.DBus.Properties", "Set",
2724 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2725 "EnterDwellTime",
2726 dbus::utility::DbusVariantType(timeMilliseconds));
2727 }
2728 if (ipsExitUtil)
2729 {
2730 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002731 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002732 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002733 {
Ed Tanous8a592812022-06-04 09:06:59 -07002734 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002735 messages::internalError(aResp->res);
2736 return;
2737 }
2738 },
2739 service, path, "org.freedesktop.DBus.Properties", "Set",
2740 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2741 "ExitUtilizationPercent",
2742 dbus::utility::DbusVariantType(*ipsExitUtil));
2743 }
2744 if (ipsExitTime)
2745 {
2746 // Convert from seconds into milliseconds for DBus
2747 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2748 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002749 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002750 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002751 {
Ed Tanous8a592812022-06-04 09:06:59 -07002752 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002753 messages::internalError(aResp->res);
2754 return;
2755 }
2756 },
2757 service, path, "org.freedesktop.DBus.Properties", "Set",
2758 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2759 "ExitDwellTime",
2760 dbus::utility::DbusVariantType(timeMilliseconds));
2761 }
George Liue99073f2022-12-09 11:06:16 +08002762 });
Chris Cain37bbf982021-09-20 10:53:09 -05002763
2764 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2765}
2766
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002767inline void handleComputerSystemHead(
2768 crow::App& app, const crow::Request& req,
2769 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2770{
2771 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2772 {
2773 return;
2774 }
2775 asyncResp->res.addHeader(
2776 boost::beast::http::field::link,
2777 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2778}
2779
Yong Lic45f0082019-10-10 14:19:01 +08002780/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002781 * SystemsCollection derived class for delivering ComputerSystems Collection
2782 * Schema
2783 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002784inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002785{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002786 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002787 .privileges(redfish::privileges::headComputerSystemCollection)
2788 .methods(boost::beast::http::verb::head)(
2789 std::bind_front(handleComputerSystemHead, std::ref(app)));
2790
2791 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002792 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002793 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002794 [&app](const crow::Request& req,
2795 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002796 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002797 {
2798 return;
2799 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002800
2801 asyncResp->res.addHeader(
2802 boost::beast::http::field::link,
2803 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002804 asyncResp->res.jsonValue["@odata.type"] =
2805 "#ComputerSystemCollection.ComputerSystemCollection";
2806 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2807 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002808
Ed Tanous002d39b2022-05-31 08:59:27 -07002809 sdbusplus::asio::getProperty<std::string>(
2810 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2811 "/xyz/openbmc_project/network/hypervisor",
2812 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002813 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002814 const std::string& /*hostName*/) {
2815 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2816 ifaceArray = nlohmann::json::array();
2817 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002818
Ed Tanous002d39b2022-05-31 08:59:27 -07002819 nlohmann::json::object_t system;
2820 system["@odata.id"] = "/redfish/v1/Systems/system";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002821 ifaceArray.emplace_back(std::move(system));
Ed Tanous002d39b2022-05-31 08:59:27 -07002822 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002823 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002824 {
2825 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2826 nlohmann::json::object_t hypervisor;
2827 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002828 ifaceArray.emplace_back(std::move(hypervisor));
Ed Tanous002d39b2022-05-31 08:59:27 -07002829 count = ifaceArray.size();
2830 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002832 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002833}
Sunitha Harish462023a2020-02-19 08:34:59 -06002834
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002835/**
2836 * Function transceives data with dbus directly.
2837 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002838inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839{
Patrick Williams89492a12023-05-10 07:51:34 -05002840 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2841 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2842 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002844 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002845
2846 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002847 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002848 if (ec)
2849 {
2850 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2851 messages::internalError(asyncResp->res);
2852 return;
2853 }
2854 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002855 },
2856 serviceName, objectPath, interfaceName, method);
2857}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002858
2859/**
Andrew Geisslerfc903b32023-05-31 14:15:42 -04002860 * Handle error responses from d-bus for system power requests
2861 */
2862inline void handleSystemActionResetError(const boost::system::error_code& ec,
2863 const sdbusplus::message_t& eMsg,
2864 std::string_view resetType,
2865 crow::Response& res)
2866{
2867 if (ec.value() == boost::asio::error::invalid_argument)
2868 {
2869 messages::actionParameterNotSupported(res, resetType, "Reset");
2870 return;
2871 }
2872
2873 if (eMsg.get_error() == nullptr)
2874 {
2875 BMCWEB_LOG_ERROR << "D-Bus response error: " << ec;
2876 messages::internalError(res);
2877 return;
2878 }
2879 std::string_view errorMessage = eMsg.get_error()->name;
2880
2881 // If operation failed due to BMC not being in Ready state, tell
2882 // user to retry in a bit
2883 if ((errorMessage ==
2884 std::string_view(
2885 "xyz.openbmc_project.State.Chassis.Error.BMCNotReady")) ||
2886 (errorMessage ==
2887 std::string_view("xyz.openbmc_project.State.Host.Error.BMCNotReady")))
2888 {
2889 BMCWEB_LOG_DEBUG << "BMC not ready, operation not allowed right now";
2890 messages::serviceTemporarilyUnavailable(res, "10");
2891 return;
2892 }
2893
2894 BMCWEB_LOG_ERROR << "System Action Reset transition fail " << ec
2895 << " sdbusplus:" << errorMessage;
2896 messages::internalError(res);
2897}
2898
2899/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002900 * SystemActionsReset class supports handle POST method for Reset action.
2901 * The class retrieves and sends data directly to D-Bus.
2902 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002903inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002904{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002905 /**
2906 * Function handles POST method request.
2907 * Analyzes POST body message before sends Reset request data to D-Bus.
2908 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002909 BMCWEB_ROUTE(app,
2910 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002911 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002912 .methods(boost::beast::http::verb::post)(
2913 [&app](const crow::Request& req,
2914 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002915 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002916 {
2917 return;
2918 }
2919 std::string resetType;
2920 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2921 resetType))
2922 {
2923 return;
2924 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002925
Ed Tanous002d39b2022-05-31 08:59:27 -07002926 // Get the command and host vs. chassis
2927 std::string command;
2928 bool hostCommand = true;
2929 if ((resetType == "On") || (resetType == "ForceOn"))
2930 {
2931 command = "xyz.openbmc_project.State.Host.Transition.On";
2932 hostCommand = true;
2933 }
2934 else if (resetType == "ForceOff")
2935 {
2936 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2937 hostCommand = false;
2938 }
2939 else if (resetType == "ForceRestart")
2940 {
2941 command =
2942 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2943 hostCommand = true;
2944 }
2945 else if (resetType == "GracefulShutdown")
2946 {
2947 command = "xyz.openbmc_project.State.Host.Transition.Off";
2948 hostCommand = true;
2949 }
2950 else if (resetType == "GracefulRestart")
2951 {
2952 command =
2953 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2954 hostCommand = true;
2955 }
2956 else if (resetType == "PowerCycle")
2957 {
2958 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2959 hostCommand = true;
2960 }
2961 else if (resetType == "Nmi")
2962 {
2963 doNMI(asyncResp);
2964 return;
2965 }
2966 else
2967 {
2968 messages::actionParameterUnknown(asyncResp->res, "Reset",
2969 resetType);
2970 return;
2971 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002972
Ed Tanous002d39b2022-05-31 08:59:27 -07002973 if (hostCommand)
2974 {
2975 crow::connections::systemBus->async_method_call(
Andrew Geisslerfc903b32023-05-31 14:15:42 -04002976 [asyncResp, resetType](const boost::system::error_code& ec,
2977 sdbusplus::message_t& sdbusErrMsg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002978 if (ec)
2979 {
Andrew Geisslerfc903b32023-05-31 14:15:42 -04002980 handleSystemActionResetError(ec, sdbusErrMsg, resetType,
2981 asyncResp->res);
2982
Ed Tanous002d39b2022-05-31 08:59:27 -07002983 return;
2984 }
2985 messages::success(asyncResp->res);
2986 },
2987 "xyz.openbmc_project.State.Host",
2988 "/xyz/openbmc_project/state/host0",
2989 "org.freedesktop.DBus.Properties", "Set",
2990 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2991 dbus::utility::DbusVariantType{command});
2992 }
2993 else
2994 {
2995 crow::connections::systemBus->async_method_call(
Andrew Geisslerfc903b32023-05-31 14:15:42 -04002996 [asyncResp, resetType](const boost::system::error_code& ec,
2997 sdbusplus::message_t& sdbusErrMsg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002998 if (ec)
2999 {
Andrew Geisslerfc903b32023-05-31 14:15:42 -04003000 handleSystemActionResetError(ec, sdbusErrMsg, resetType,
3001 asyncResp->res);
Ed Tanous002d39b2022-05-31 08:59:27 -07003002 return;
3003 }
3004 messages::success(asyncResp->res);
3005 },
3006 "xyz.openbmc_project.State.Chassis",
3007 "/xyz/openbmc_project/state/chassis0",
3008 "org.freedesktop.DBus.Properties", "Set",
3009 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
3010 dbus::utility::DbusVariantType{command});
3011 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003012 });
3013}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003014
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003015inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003016 App& app, const crow::Request& req,
3017 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3018{
3019 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3020 {
3021 return;
3022 }
3023
3024 asyncResp->res.addHeader(
3025 boost::beast::http::field::link,
3026 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3027}
3028
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003029inline void afterPortRequest(
3030 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3031 const boost::system::error_code& ec,
3032 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3033{
3034 if (ec)
3035 {
3036 messages::internalError(asyncResp->res);
3037 return;
3038 }
3039 for (const auto& data : socketData)
3040 {
3041 const std::string& socketPath = get<0>(data);
3042 const std::string& protocolName = get<1>(data);
3043 bool isProtocolEnabled = get<2>(data);
3044 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3045 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3046 // need to retrieve port number for
3047 // obmc-console-ssh service
3048 if (protocolName == "SSH")
3049 {
3050 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003051 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003052 int portNumber) {
3053 if (ec1)
3054 {
3055 messages::internalError(asyncResp->res);
3056 return;
3057 }
3058 nlohmann::json& dataJson1 =
3059 asyncResp->res.jsonValue["SerialConsole"];
3060 dataJson1[protocolName]["Port"] = portNumber;
3061 });
3062 }
3063 }
3064}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003065/**
Ed Tanous66173382018-08-15 18:20:59 -07003066 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003067 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003068inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003069{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003070 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
3071 .privileges(redfish::privileges::headComputerSystem)
3072 .methods(boost::beast::http::verb::head)(
3073 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07003074 /**
3075 * Functions triggers appropriate requests on DBus
3076 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003077 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003078 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003079 .methods(boost::beast::http::verb::get)(
3080 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003081 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3082 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003083 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003084 {
3085 return;
3086 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003087
3088 if (systemName == "hypervisor")
3089 {
3090 handleHypervisorSystemGet(asyncResp);
3091 return;
3092 }
3093
Ed Tanous22d268c2022-05-19 09:39:07 -07003094 if (systemName != "system")
3095 {
3096 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3097 systemName);
3098 return;
3099 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003100 asyncResp->res.addHeader(
3101 boost::beast::http::field::link,
3102 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003103 asyncResp->res.jsonValue["@odata.type"] =
3104 "#ComputerSystem.v1_16_0.ComputerSystem";
3105 asyncResp->res.jsonValue["Name"] = "system";
3106 asyncResp->res.jsonValue["Id"] = "system";
3107 asyncResp->res.jsonValue["SystemType"] = "Physical";
3108 asyncResp->res.jsonValue["Description"] = "Computer System";
3109 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ninad Palsule5fd0aaf2023-04-20 15:11:21 -05003110 if constexpr (bmcwebEnableProcMemStatus)
3111 {
3112 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3113 "Disabled";
3114 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3115 "Disabled";
3116 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -05003117 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3118 uint64_t(0);
Ed Tanous002d39b2022-05-31 08:59:27 -07003119 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003120
Ed Tanous002d39b2022-05-31 08:59:27 -07003121 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3122 "/redfish/v1/Systems/system/Processors";
3123 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3124 "/redfish/v1/Systems/system/Memory";
3125 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3126 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003127 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3128 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003129
Ed Tanous002d39b2022-05-31 08:59:27 -07003130 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3131 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3132 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3133 ["@Redfish.ActionInfo"] =
3134 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003135
Ed Tanous002d39b2022-05-31 08:59:27 -07003136 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3137 "/redfish/v1/Systems/system/LogServices";
3138 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3139 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003140
Ed Tanous002d39b2022-05-31 08:59:27 -07003141 nlohmann::json::array_t managedBy;
3142 nlohmann::json& manager = managedBy.emplace_back();
3143 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3144 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3145 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3146 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003147
Ed Tanous002d39b2022-05-31 08:59:27 -07003148 // Fill in SerialConsole info
3149 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3150 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3151 true;
Ed Tanous14766872022-03-15 10:44:42 -07003152
Ed Tanous002d39b2022-05-31 08:59:27 -07003153 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3154 true;
3155 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3156 asyncResp->res
3157 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3158 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003159 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3160 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003161
3162#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003163 // Fill in GraphicalConsole info
3164 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3165 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3166 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003167 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3168 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003169
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003170#endif // BMCWEB_ENABLE_KVM
James Feistb49ac872019-05-21 15:12:01 -07003171
Ed Tanous002d39b2022-05-31 08:59:27 -07003172 auto health = std::make_shared<HealthPopulate>(asyncResp);
Willy Tu13451e32023-05-24 16:08:18 -07003173 if constexpr (bmcwebEnableHealthPopulate)
3174 {
3175 constexpr std::array<std::string_view, 4> inventoryForSystems{
3176 "xyz.openbmc_project.Inventory.Item.Dimm",
3177 "xyz.openbmc_project.Inventory.Item.Cpu",
3178 "xyz.openbmc_project.Inventory.Item.Drive",
3179 "xyz.openbmc_project.Inventory.Item.StorageController"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003180
Willy Tu13451e32023-05-24 16:08:18 -07003181 dbus::utility::getSubTreePaths(
3182 "/", 0, inventoryForSystems,
3183 [health](const boost::system::error_code& ec,
3184 const std::vector<std::string>& resp) {
3185 if (ec)
3186 {
3187 // no inventory
3188 return;
3189 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003190
Willy Tu13451e32023-05-24 16:08:18 -07003191 health->inventory = resp;
3192 });
3193 health->populate();
3194 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003195
Ed Tanous002d39b2022-05-31 08:59:27 -07003196 getMainChassisId(asyncResp,
3197 [](const std::string& chassisId,
3198 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3199 nlohmann::json::array_t chassisArray;
3200 nlohmann::json& chassis = chassisArray.emplace_back();
Ed Tanousef4c65b2023-04-24 15:28:50 -07003201 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3202 chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003203 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3204 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003205
Ed Tanous002d39b2022-05-31 08:59:27 -07003206 getLocationIndicatorActive(asyncResp);
3207 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3208 getIndicatorLedState(asyncResp);
3209 getComputerSystem(asyncResp, health);
3210 getHostState(asyncResp);
3211 getBootProperties(asyncResp);
3212 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003213 getBootProgressLastStateTime(asyncResp);
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -05003214 pcie_util::getPCIeDeviceList(asyncResp, "PCIeDevices");
Ed Tanous002d39b2022-05-31 08:59:27 -07003215 getHostWatchdogTimer(asyncResp);
3216 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003217 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003218 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003219#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003220 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003221#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003222 getTrustedModuleRequiredToBoot(asyncResp);
3223 getPowerMode(asyncResp);
3224 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003225 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003226
Ed Tanous22d268c2022-05-19 09:39:07 -07003227 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003228 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003229 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003230 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003231 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3232 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003233 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003234 {
3235 return;
3236 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003237 if (systemName != "system")
3238 {
3239 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3240 systemName);
3241 return;
3242 }
3243
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003244 asyncResp->res.addHeader(
3245 boost::beast::http::field::link,
3246 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3247
Ed Tanous002d39b2022-05-31 08:59:27 -07003248 std::optional<bool> locationIndicatorActive;
3249 std::optional<std::string> indicatorLed;
3250 std::optional<std::string> assetTag;
3251 std::optional<std::string> powerRestorePolicy;
3252 std::optional<std::string> powerMode;
3253 std::optional<bool> wdtEnable;
3254 std::optional<std::string> wdtTimeOutAction;
3255 std::optional<std::string> bootSource;
3256 std::optional<std::string> bootType;
3257 std::optional<std::string> bootEnable;
3258 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003259 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003260 std::optional<bool> bootTrustedModuleRequired;
3261 std::optional<bool> ipsEnable;
3262 std::optional<uint8_t> ipsEnterUtil;
3263 std::optional<uint64_t> ipsEnterTime;
3264 std::optional<uint8_t> ipsExitUtil;
3265 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003266
Ed Tanous002d39b2022-05-31 08:59:27 -07003267 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003268 if (!json_util::readJsonPatch(
3269 req, asyncResp->res,
3270 "IndicatorLED", indicatorLed,
3271 "LocationIndicatorActive", locationIndicatorActive,
3272 "AssetTag", assetTag,
3273 "PowerRestorePolicy", powerRestorePolicy,
3274 "PowerMode", powerMode,
3275 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3276 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3277 "Boot/BootSourceOverrideTarget", bootSource,
3278 "Boot/BootSourceOverrideMode", bootType,
3279 "Boot/BootSourceOverrideEnabled", bootEnable,
3280 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003281 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003282 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3283 "IdlePowerSaver/Enabled", ipsEnable,
3284 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3285 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3286 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3287 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3288 {
3289 return;
3290 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003291 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003292
Ed Tanous002d39b2022-05-31 08:59:27 -07003293 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003294
Ed Tanous002d39b2022-05-31 08:59:27 -07003295 if (assetTag)
3296 {
3297 setAssetTag(asyncResp, *assetTag);
3298 }
James Feistb49ac872019-05-21 15:12:01 -07003299
Ed Tanous002d39b2022-05-31 08:59:27 -07003300 if (wdtEnable || wdtTimeOutAction)
3301 {
3302 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3303 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003304
Ed Tanous002d39b2022-05-31 08:59:27 -07003305 if (bootSource || bootType || bootEnable)
3306 {
3307 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3308 }
3309 if (bootAutomaticRetry)
3310 {
3311 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3312 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003313
Corey Hardesty797d5da2022-04-26 17:54:52 +08003314 if (bootAutomaticRetryAttempts)
3315 {
3316 setAutomaticRetryAttempts(asyncResp,
3317 bootAutomaticRetryAttempts.value());
3318 }
3319
Ed Tanous002d39b2022-05-31 08:59:27 -07003320 if (bootTrustedModuleRequired)
3321 {
3322 setTrustedModuleRequiredToBoot(asyncResp,
3323 *bootTrustedModuleRequired);
3324 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003325
Ed Tanous002d39b2022-05-31 08:59:27 -07003326 if (locationIndicatorActive)
3327 {
3328 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3329 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003330
Ed Tanous002d39b2022-05-31 08:59:27 -07003331 // TODO (Gunnar): Remove IndicatorLED after enough time has
3332 // passed
3333 if (indicatorLed)
3334 {
3335 setIndicatorLedState(asyncResp, *indicatorLed);
3336 asyncResp->res.addHeader(boost::beast::http::field::warning,
3337 "299 - \"IndicatorLED is deprecated. Use "
3338 "LocationIndicatorActive instead.\"");
3339 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003340
Ed Tanous002d39b2022-05-31 08:59:27 -07003341 if (powerRestorePolicy)
3342 {
3343 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3344 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003345
Ed Tanous002d39b2022-05-31 08:59:27 -07003346 if (powerMode)
3347 {
3348 setPowerMode(asyncResp, *powerMode);
3349 }
Chris Cain37bbf982021-09-20 10:53:09 -05003350
Ed Tanous002d39b2022-05-31 08:59:27 -07003351 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3352 ipsExitTime)
3353 {
3354 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3355 ipsExitUtil, ipsExitTime);
3356 }
3357 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003358}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303359
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003360inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003361 crow::App& app, const crow::Request& req,
3362 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3363{
3364 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3365 {
3366 return;
3367 }
3368 asyncResp->res.addHeader(
3369 boost::beast::http::field::link,
3370 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3371}
3372
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303373/**
3374 * SystemResetActionInfo derived class for delivering Computer Systems
3375 * ResetType AllowableValues using ResetInfo schema.
3376 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003377inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303378{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003379 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3380 .privileges(redfish::privileges::headActionInfo)
3381 .methods(boost::beast::http::verb::head)(std::bind_front(
3382 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303383 /**
3384 * Functions triggers appropriate requests on DBus
3385 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003386 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003387 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003388 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003389 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003390 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3391 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003392 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003393 {
3394 return;
3395 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003396
3397 if (systemName == "hypervisor")
3398 {
3399 handleHypervisorResetActionGet(asyncResp);
3400 return;
3401 }
3402
Ed Tanous22d268c2022-05-19 09:39:07 -07003403 if (systemName != "system")
3404 {
3405 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3406 systemName);
3407 return;
3408 }
3409
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003410 asyncResp->res.addHeader(
3411 boost::beast::http::field::link,
3412 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003413
Ed Tanous002d39b2022-05-31 08:59:27 -07003414 asyncResp->res.jsonValue["@odata.id"] =
3415 "/redfish/v1/Systems/system/ResetActionInfo";
3416 asyncResp->res.jsonValue["@odata.type"] =
3417 "#ActionInfo.v1_1_2.ActionInfo";
3418 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3419 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003420
3421 nlohmann::json::array_t parameters;
3422 nlohmann::json::object_t parameter;
3423
3424 parameter["Name"] = "ResetType";
3425 parameter["Required"] = true;
3426 parameter["DataType"] = "String";
3427 nlohmann::json::array_t allowableValues;
3428 allowableValues.emplace_back("On");
3429 allowableValues.emplace_back("ForceOff");
3430 allowableValues.emplace_back("ForceOn");
3431 allowableValues.emplace_back("ForceRestart");
3432 allowableValues.emplace_back("GracefulRestart");
3433 allowableValues.emplace_back("GracefulShutdown");
3434 allowableValues.emplace_back("PowerCycle");
3435 allowableValues.emplace_back("Nmi");
3436 parameter["AllowableValues"] = std::move(allowableValues);
3437 parameters.emplace_back(std::move(parameter));
3438
3439 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003440 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003441}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003442} // namespace redfish