blob: ec67ebc26eab196a7b92687b7a9d127479d6e34e [file] [log] [blame]
Carol Wangd82a3ac2019-11-21 13:56:38 +08001#pragma once
2
3#include "node.hpp"
4
Gunnar Mills72d566d2020-07-21 12:44:00 -05005#include <utils/fw_utils.hpp>
Kuiying Wang212f6bc2020-09-04 19:24:25 +08006
Carol Wangd82a3ac2019-11-21 13:56:38 +08007namespace redfish
8{
Kuiying Wang212f6bc2020-09-04 19:24:25 +08009
10/*baseBIOSTable
11map{attributeName,struct{attributeType,readonlyStatus,displayname,
12 description,menuPath,current,default,
13 array{struct{optionstring,optionvalue}}}}
14*/
15using BiosBaseTableType = std::vector<std::pair<
16 std::string,
17 std::tuple<
18 std::string, bool, std::string, std::string, std::string,
19 std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
20 std::vector<
21 std::tuple<std::string, std::variant<int64_t, std::string>>>>>>;
22using BiosBaseTableItemType = std::pair<
23 std::string,
24 std::tuple<
25 std::string, bool, std::string, std::string, std::string,
26 std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
27 std::vector<
28 std::tuple<std::string, std::variant<int64_t, std::string>>>>>;
29using OptionsItemType =
30 std::tuple<std::string, std::variant<int64_t, std::string>>;
31
32enum BiosBaseTableIndex
33{
34 biosBaseAttrType = 0,
35 biosBaseReadonlyStatus,
36 biosBaseDisplayName,
37 biosBaseDescription,
38 biosBaseMenuPath,
39 biosBaseCurrValue,
40 biosBaseDefaultValue,
41 biosBaseOptions
42};
43enum OptionsItemIndex
44{
45 optItemType = 0,
46 optItemValue
47};
48/*
49 The Pending attribute name and new value.
50 ex- { {"QuietBoot",Type.Integer, 0x1},
51 { "DdrFreqLimit",Type.String,"2933"}
52 }
53*/
54using PendingAttributesType = std::vector<std::pair<
55 std::string, std::tuple<std::string, std::variant<int64_t, std::string>>>>;
56using PendingAttributesItemType =
57 std::pair<std::string,
58 std::tuple<std::string, std::variant<int64_t, std::string>>>;
59enum PendingAttributesIndex
60{
61 pendingAttrType = 0,
62 pendingAttrValue
63};
64static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
65{
66 std::string ret;
67 if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
68 "AttributeType.Enumeration")
69 {
70 ret = "Enumeration";
71 }
72 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
73 "Manager.AttributeType.String")
74 {
75 ret = "String";
76 }
77 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
78 "Manager.AttributeType.Password")
79 {
80 ret = "Password";
81 }
82 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
83 "Manager.AttributeType.Integer")
84 {
85 ret = "Integer";
86 }
87 else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
88 "Manager.AttributeType.Boolean")
89 {
90 ret = "Boolean";
91 }
92 else
93 {
94 ret = "UNKNOWN";
95 }
96
97 return ret;
98}
99static std::string mapBoundTypeToRedfish(const std::string_view typeDbus)
100{
101 std::string ret;
102 if (typeDbus ==
103 "xyz.openbmc_project.BIOSConfig.Manager.BoundType.ScalarIncrement")
104 {
105 ret = "ScalarIncrement";
106 }
107 else if (typeDbus ==
108 "xyz.openbmc_project.BIOSConfig.Manager.BoundType.LowerBound")
109 {
110 ret = "LowerBound";
111 }
112 else if (typeDbus ==
113 "xyz.openbmc_project.BIOSConfig.Manager.BoundType.UpperBound")
114 {
115 ret = "UpperBound";
116 }
117 else if (typeDbus ==
118 "xyz.openbmc_project.BIOSConfig.Manager.BoundType.MinStringLength")
119 {
120 ret = "MinLength";
121 }
122 else if (typeDbus ==
123 "xyz.openbmc_project.BIOSConfig.Manager.BoundType.MaxStringLength")
124 {
125 ret = "MaxLength";
126 }
127 else if (typeDbus ==
128 "xyz.openbmc_project.BIOSConfig.Manager.BoundType.OneOf")
129 {
130 ret = "OneOf";
131 }
132 else
133 {
134 ret = "UNKNOWN";
135 }
136
137 return ret;
138}
139
Carol Wangd82a3ac2019-11-21 13:56:38 +0800140/**
141 * BiosService class supports handle get method for bios.
142 */
143class BiosService : public Node
144{
145 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700146 BiosService(App& app) : Node(app, "/redfish/v1/Systems/system/Bios/")
Carol Wangd82a3ac2019-11-21 13:56:38 +0800147 {
148 entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}};
149 }
150
151 private:
Ed Tanouscb13a392020-07-25 19:02:03 +0000152 void doGet(crow::Response& res, const crow::Request&,
153 const std::vector<std::string>&) override
Carol Wangd82a3ac2019-11-21 13:56:38 +0800154 {
155 auto asyncResp = std::make_shared<AsyncResp>(res);
156
157 asyncResp->res.jsonValue["@odata.id"] =
158 "/redfish/v1/Systems/system/Bios";
159 asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
160 asyncResp->res.jsonValue["Name"] = "BIOS Configuration";
161 asyncResp->res.jsonValue["Description"] = "BIOS Configuration Service";
162 asyncResp->res.jsonValue["Id"] = "BIOS";
163 asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = {
164 {"target",
165 "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}};
Gunnar Mills72d566d2020-07-21 12:44:00 -0500166
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500167 // Get the ActiveSoftwareImage and SoftwareImages
168 fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose,
169 "", true);
Kuiying Wang212f6bc2020-09-04 19:24:25 +0800170 asyncResp->res.jsonValue["@Redfish.Settings"] = {
171 {"@odata.type", "#Settings.v1_3_0.Settings"},
172 {"SettingsObject",
173 {{"@odata.id", "/redfish/v1/Systems/system/Bios/Settings"}}}};
174 asyncResp->res.jsonValue["AttributeRegistry"] = "BiosAttributeRegistry";
175 asyncResp->res.jsonValue["Attributes"] = {};
176
177 crow::connections::systemBus->async_method_call(
178 [asyncResp](const boost::system::error_code ec,
179 const GetObjectType& getObjectType) {
180 if (ec)
181 {
182 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
183 << ec;
184 messages::internalError(asyncResp->res);
185
186 return;
187 }
188 const std::string& service = getObjectType.begin()->first;
189
190 crow::connections::systemBus->async_method_call(
191 [asyncResp](
192 const boost::system::error_code ec,
193 const std::variant<BiosBaseTableType>& retBiosTable) {
194 if (ec)
195 {
196 BMCWEB_LOG_ERROR << "getBiosAttributes DBUS error: "
197 << ec;
198 messages::internalError(asyncResp->res);
199 return;
200 }
201 const BiosBaseTableType* baseBiosTable =
202 std::get_if<BiosBaseTableType>(&retBiosTable);
203 nlohmann::json& attributesJson =
204 asyncResp->res.jsonValue["Attributes"];
205 if (baseBiosTable == nullptr)
206 {
207 BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
208 messages::internalError(asyncResp->res);
209 return;
210 }
211 for (const BiosBaseTableItemType& item : *baseBiosTable)
212 {
213 const std::string& key = item.first;
214 const std::string& itemType =
215 std::get<biosBaseAttrType>(item.second);
216 std::string attrType =
217 mapAttrTypeToRedfish(itemType);
218 if (attrType == "String")
219 {
220 const std::string* currValue =
221 std::get_if<std::string>(
222 &std::get<biosBaseCurrValue>(
223 item.second));
224 attributesJson.emplace(key, currValue != nullptr
225 ? *currValue
226 : "");
227 }
228 else if (attrType == "Integer")
229 {
230 const int64_t* currValue = std::get_if<int64_t>(
231 &std::get<biosBaseCurrValue>(item.second));
232 attributesJson.emplace(
233 key, currValue != nullptr ? *currValue : 0);
234 }
235 else
236 {
237 BMCWEB_LOG_ERROR
238 << "Unsupported attribute type.";
239 messages::internalError(asyncResp->res);
240 }
241 }
242 },
243 service, "/xyz/openbmc_project/bios_config/manager",
244 "org.freedesktop.DBus.Properties", "Get",
245 "xyz.openbmc_project.BIOSConfig.Manager", "BaseBIOSTable");
246 },
247 "xyz.openbmc_project.ObjectMapper",
248 "/xyz/openbmc_project/object_mapper",
249 "xyz.openbmc_project.ObjectMapper", "GetObject",
250 "/xyz/openbmc_project/bios_config/manager",
251 std::array<const char*, 0>());
252 }
253};
254
255/**
256 * BiosSettings class supports handle GET/PATCH method for
257 * BIOS configuration pending settings.
258 */
259class BiosSettings : public Node
260{
261 public:
262 BiosSettings(App& app) :
263 Node(app, "/redfish/v1/Systems/system/Bios/Settings")
264 {
265 entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}};
266 }
267
268 private:
269 void doGet(crow::Response& res, const crow::Request&,
270 const std::vector<std::string>&) override
271 {
272 auto asyncResp = std::make_shared<AsyncResp>(res);
273 asyncResp->res.jsonValue["@odata.id"] =
274 "/redfish/v1/Systems/system/Bios/Settings";
275 asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
276 asyncResp->res.jsonValue["Name"] = "Bios Settings";
277 asyncResp->res.jsonValue["Id"] = "BiosSettings";
278 asyncResp->res.jsonValue["AttributeRegistry"] = "BiosAttributeRegistry";
279 asyncResp->res.jsonValue["Attributes"] = {};
280
281 crow::connections::systemBus->async_method_call(
282 [asyncResp](const boost::system::error_code ec,
283 const GetObjectType& getObjectType) {
284 if (ec)
285 {
286 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
287 << ec;
288 messages::internalError(asyncResp->res);
289
290 return;
291 }
292 std::string service = getObjectType.begin()->first;
293
294 crow::connections::systemBus->async_method_call(
295 [asyncResp](const boost::system::error_code ec,
296 const std::variant<PendingAttributesType>&
297 retPendingAttributes) {
298 if (ec)
299 {
300 BMCWEB_LOG_ERROR << "getBiosSettings DBUS error: "
301 << ec;
302 messages::resourceNotFound(asyncResp->res,
303 "Systems/system/Bios",
304 "Settings");
305 return;
306 }
307 const PendingAttributesType* pendingAttributes =
308 std::get_if<PendingAttributesType>(
309 &retPendingAttributes);
310 nlohmann::json& attributesJson =
311 asyncResp->res.jsonValue["Attributes"];
312 if (pendingAttributes == nullptr)
313 {
314 BMCWEB_LOG_ERROR << "pendingAttributes == nullptr ";
315 messages::internalError(asyncResp->res);
316 return;
317 }
318 for (const PendingAttributesItemType& item :
319 *pendingAttributes)
320 {
321 const std::string& key = item.first;
322 const std::string& itemType =
323 std::get<pendingAttrType>(item.second);
324 std::string attrType =
325 mapAttrTypeToRedfish(itemType);
326 if (attrType == "String")
327 {
328 const std::string* currValue =
329 std::get_if<std::string>(
330 &std::get<pendingAttrValue>(
331 item.second));
332 attributesJson.emplace(key, currValue != nullptr
333 ? *currValue
334 : "");
335 }
336 else if (attrType == "Integer")
337 {
338 const int64_t* currValue = std::get_if<int64_t>(
339 &std::get<pendingAttrValue>(item.second));
340 attributesJson.emplace(
341 key, currValue != nullptr ? *currValue : 0);
342 }
343 else
344 {
345 BMCWEB_LOG_ERROR
346 << "Unsupported attribute type.";
347 messages::internalError(asyncResp->res);
348 }
349 }
350 },
351 service, "/xyz/openbmc_project/bios_config/manager",
352 "org.freedesktop.DBus.Properties", "Get",
353 "xyz.openbmc_project.BIOSConfig.Manager",
354 "PendingAttributes");
355 },
356 "xyz.openbmc_project.ObjectMapper",
357 "/xyz/openbmc_project/object_mapper",
358 "xyz.openbmc_project.ObjectMapper", "GetObject",
359 "/xyz/openbmc_project/bios_config/manager",
360 std::array<const char*, 0>());
361 }
362};
363/**
364 * BiosAttributeRegistry class supports handle get method for BIOS attribute
365 * registry.
366 */
367class BiosAttributeRegistry : public Node
368{
369 public:
370 BiosAttributeRegistry(App& app) :
371 Node(app, "/redfish/v1/Registries/BiosAttributeRegistry/"
372 "BiosAttributeRegistry")
373 {
374 entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}};
375 }
376
377 private:
378 void doGet(crow::Response& res, const crow::Request&,
379 const std::vector<std::string>&) override
380 {
381 auto asyncResp = std::make_shared<AsyncResp>(res);
382 asyncResp->res.jsonValue["@odata.id"] =
383 "/redfish/v1/Registries/BiosAttributeRegistry/"
384 "BiosAttributeRegistry";
385 asyncResp->res.jsonValue["@odata.type"] =
386 "#AttributeRegistry.v1_3_2.AttributeRegistry";
387 asyncResp->res.jsonValue["Name"] = "Bios Attribute Registry";
388 asyncResp->res.jsonValue["Id"] = "BiosAttributeRegistry";
389 asyncResp->res.jsonValue["RegistryVersion"] = "1.0.0";
390 asyncResp->res.jsonValue["Language"] = "en";
391 asyncResp->res.jsonValue["OwningEntity"] = "OpenBMC";
392 asyncResp->res.jsonValue["RegistryEntries"]["Attributes"] =
393 nlohmann::json::array();
394
395 crow::connections::systemBus->async_method_call(
396 [asyncResp](const boost::system::error_code ec,
397 const GetObjectType& getObjectType) {
398 if (ec)
399 {
400 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
401 << ec;
402 messages::internalError(asyncResp->res);
403
404 return;
405 }
406 std::string service = getObjectType.begin()->first;
407
408 crow::connections::systemBus->async_method_call(
409 [asyncResp](
410 const boost::system::error_code ec,
411 const std::variant<BiosBaseTableType>& retBiosTable) {
412 if (ec)
413 {
414 BMCWEB_LOG_ERROR
415 << "getBiosAttributeRegistry DBUS error: "
416 << ec;
417 messages::resourceNotFound(
418 asyncResp->res, "Registries/Bios", "Bios");
419 return;
420 }
421 const BiosBaseTableType* baseBiosTable =
422 std::get_if<BiosBaseTableType>(&retBiosTable);
423 nlohmann::json& attributeArray =
424 asyncResp->res
425 .jsonValue["RegistryEntries"]["Attributes"];
426 if (baseBiosTable == nullptr)
427 {
428 BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
429 messages::internalError(asyncResp->res);
430 return;
431 }
432 for (const BiosBaseTableItemType& item : *baseBiosTable)
433 {
434 nlohmann::json optionsArray =
435 nlohmann::json::array();
436 const std::string& itemType =
437 std::get<biosBaseAttrType>(item.second);
438 std::string attrType =
439 mapAttrTypeToRedfish(itemType);
440 if (attrType == "UNKNOWN")
441 {
442 BMCWEB_LOG_ERROR << "attrType == UNKNOWN";
443 messages::internalError(asyncResp->res);
444 return;
445 }
446 nlohmann::json attributeItem;
447 attributeItem["AttributeName"] = item.first;
448 attributeItem["Type"] = attrType;
449 attributeItem["ReadOnly"] =
450 std::get<biosBaseReadonlyStatus>(item.second);
451 attributeItem["DisplayName"] =
452 std::get<biosBaseDisplayName>(item.second);
453 attributeItem["HelpText"] =
454 std::get<biosBaseDescription>(item.second);
455 if ((std::get<biosBaseMenuPath>(item.second)) != "")
456 {
457 attributeItem["MenuPath"] =
458 std::get<biosBaseMenuPath>(item.second);
459 }
460
461 if (attrType == "String")
462 {
463 const std::string* currValue =
464 std::get_if<std::string>(
465 &std::get<biosBaseCurrValue>(
466 item.second));
467 const std::string* defValue =
468 std::get_if<std::string>(
469 &std::get<biosBaseDefaultValue>(
470 item.second));
471 if (currValue && *currValue != "")
472 {
473 attributeItem["CurrentValue"] = *currValue;
474 }
475 if (defValue && *defValue != "")
476 {
477 attributeItem["DefaultValue"] = *defValue;
478 }
479 }
480 else if (attrType == "Integer")
481 {
482 const int64_t* currValue = std::get_if<int64_t>(
483 &std::get<biosBaseCurrValue>(item.second));
484 const int64_t* defValue = std::get_if<int64_t>(
485 &std::get<biosBaseDefaultValue>(
486 item.second));
487 attributeItem["CurrentValue"] =
488 currValue != nullptr ? *currValue : 0;
489 attributeItem["DefaultValue"] =
490 defValue != nullptr ? *defValue : 0;
491 }
492 else
493 {
494 BMCWEB_LOG_ERROR
495 << "Unsupported attribute type.";
496 messages::internalError(asyncResp->res);
497 return;
498 }
499
500 const std::vector<OptionsItemType>& optionsVector =
501 std::get<biosBaseOptions>(item.second);
502 for (const OptionsItemType& optItem : optionsVector)
503 {
504 nlohmann::json optItemJson;
505 const std::string& strOptItemType =
506 std::get<optItemType>(optItem);
507 std::string optItemTypeRedfish =
508 mapBoundTypeToRedfish(strOptItemType);
509 if (optItemTypeRedfish == "UNKNOWN")
510 {
511 BMCWEB_LOG_ERROR
512 << "optItemTypeRedfish == UNKNOWN";
513 messages::internalError(asyncResp->res);
514 return;
515 }
516 if (optItemTypeRedfish == "OneOf")
517 {
518 const std::string* currValue =
519 std::get_if<std::string>(
520 &std::get<optItemValue>(optItem));
521 if (currValue != nullptr)
522 {
523 optItemJson["ValueName"] = *currValue;
524 optionsArray.push_back(optItemJson);
525 }
526 }
527 else
528 {
529 const int64_t* currValue =
530 std::get_if<int64_t>(
531 &std::get<optItemValue>(optItem));
532 if (currValue != nullptr)
533 {
534 attributeItem[optItemTypeRedfish] =
535 *currValue;
536 }
537 }
538 }
539
540 if (optionsArray.size() > 0)
541 {
542 attributeItem["Value"] = optionsArray;
543 }
544 attributeArray.push_back(attributeItem);
545 }
546 },
547 service, "/xyz/openbmc_project/bios_config/manager",
548 "org.freedesktop.DBus.Properties", "Get",
549 "xyz.openbmc_project.BIOSConfig.Manager", "BaseBIOSTable");
550 },
551 "xyz.openbmc_project.ObjectMapper",
552 "/xyz/openbmc_project/object_mapper",
553 "xyz.openbmc_project.ObjectMapper", "GetObject",
554 "/xyz/openbmc_project/bios_config/manager",
555 std::array<const char*, 0>());
Carol Wangd82a3ac2019-11-21 13:56:38 +0800556 }
557};
558/**
559 * BiosReset class supports handle POST method for Reset bios.
560 * The class retrieves and sends data directly to D-Bus.
561 */
562class BiosReset : public Node
563{
564 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700565 BiosReset(App& app) :
Carol Wangd82a3ac2019-11-21 13:56:38 +0800566 Node(app, "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios/")
567 {
568 entityPrivileges = {
569 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
570 }
571
572 private:
573 /**
574 * Function handles POST method request.
575 * Analyzes POST body message before sends Reset request data to D-Bus.
576 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000577 void doPost(crow::Response& res, const crow::Request&,
578 const std::vector<std::string>&) override
Carol Wangd82a3ac2019-11-21 13:56:38 +0800579 {
580 auto asyncResp = std::make_shared<AsyncResp>(res);
581
582 crow::connections::systemBus->async_method_call(
583 [asyncResp](const boost::system::error_code ec) {
584 if (ec)
585 {
586 BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec;
587 messages::internalError(asyncResp->res);
588 return;
589 }
590 },
591 "org.open_power.Software.Host.Updater",
592 "/xyz/openbmc_project/software",
593 "xyz.openbmc_project.Common.FactoryReset", "Reset");
594 }
595};
Gunnar Mills72d566d2020-07-21 12:44:00 -0500596} // namespace redfish