summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch874
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch148
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch53
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch117
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch46
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch963
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch76
7 files changed, 2277 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch
new file mode 100644
index 000000000..409a2af3f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch
@@ -0,0 +1,874 @@
+From 8b21bce7fa0974c454e4bed539be0475738ee21e Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Fri, 4 Sep 2020 19:24:25 +0800
+Subject: [PATCH] Define Redfish interface "/Registries/Bios" and enable
+ Attributes property
+
+1. Define Redfish interface "/Registries/Bios" for BIOS Attribute Registry
+ RBC Daemon provide method to get BIOS attribute registry.
+2. Eanble Attributes property for BIOS resource
+3. Define Redfish interface "/Systems/system/Bios/Settings" for BIOS
+settings
+4. RBC daemon is at
+https://gerrit.openbmc-project.xyz/#/c/openbmc/bios-settings-mgr/+/35563/
+5. IPMI command implementation is at
+https://gerrit.openbmc-project.xyz/#/c/openbmc/intel-ipmi-oem/+/30827/
+6. Property design is at
+https://github.com/openbmc/phosphor-dbus-interfaces/tree/master/xyz/openbmc_project/BIOSConfig
+7. Design doc is at
+https://github.com/openbmc/docs/blob/master/designs/remote-bios-configuration.md
+8. There will be 95 test cases for this feature in the validation team.
+
+Tested:
+
+1. Use postman (Redfish tool) could get all the attributes in bios
+resouce, get bios settings, get bios attribute
+registry.
+https://IP_ADDR/redfish/v1/Systems/system/Bios
+{
+ "@Redfish.Settings": {
+ "@odata.type": "#Settings.v1_3_0.Settings",
+ "SettingsObject": {
+ "@odata.id": "/redfish/v1/Systems/system/Bios/Settings"
+ }
+ },
+ "@odata.id": "/redfish/v1/Systems/system/Bios",
+ "@odata.type": "#Bios.v1_1_0.Bios",
+ "Actions": {
+ "#Bios.ChangePassword": {
+ "target": "/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword"
+ },
+ "#Bios.ResetBios": {
+ "target": "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"
+ }
+ },
+ "AttributeRegistry": "BiosAttributeRegistry",
+ "Attributes": {
+ "attr0": "current value"
+ },
+ "Description": "BIOS Configuration Service",
+ "Id": "BIOS",
+ "Links": {
+ "ActiveSoftwareImage": {
+ "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
+ },
+ "SoftwareImages": [
+ {
+ "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
+ }
+ ],
+ "SoftwareImages@odata.count": 1
+ },
+ "Name": "BIOS Configuration"
+}
+
+Redfish interface: https://BMCIP/redfish/v1/Registries/BiosAttributeRegistry
+{
+ "@odata.id": "/redfish/v1/Registries/BiosAttributeRegistry",
+ "@odata.type": "#MessageRegistryFile.v1_1_0.MessageRegistryFile",
+ "Description": "BiosAttributeRegistry Message Registry File Location",
+ "Id": "BiosAttributeRegistry",
+ "Languages": [
+ "en"
+ ],
+ "Languages@odata.count": 1,
+ "Location": [
+ {
+ "Language": "en",
+ "Uri": "/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry"
+ }
+ ],
+ "Location@odata.count": 1,
+ "Name": "BiosAttributeRegistry Message Registry File",
+ "Registry": "BiosAttributeRegistry.1.0.0"
+}
+
+Redfish interface: https://BMCIP/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry
+{
+ "@odata.id": "/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry",
+ "@odata.type": "#AttributeRegistry.v1_3_2.AttributeRegistry",
+ "Id": "BiosAttributeRegistry",
+ "Language": "en",
+ "Name": "Bios Attribute Registry",
+ "OwningEntity": "OpenBMC",
+ "RegistryEntries": {
+ "Attributes": [
+ {
+ "AttributeName": "attr0",
+ "CurrentValue": "current value",
+ "DefaultValue": "default value",
+ "DisplayName": "display name for attr0",
+ "HelpText": "description for attr0",
+ "MenuPath": "./menu/path/for/attr0",
+ "ReadOnly": false,
+ "Type": "String",
+ "Value": []
+ }
+ ]
+ },
+ "RegistryVersion": "1.0.0"
+}
+
+https://BMC_IPADDR/redfish/v1/Systems/system/Bios/Settings
+{
+ "@odata.id": "/redfish/v1/Systems/system/Bios/Settings",
+ "@odata.type": "#Bios.v1_1_0.Bios",
+ "AttributeRegistry": "BiosAttributeRegistry",
+ "Attributes": {
+ "QuietBoot": "0x0"
+ },
+ "Id": "BiosSettingsV1",
+ "Name": "Bios Settings Version 1"
+}
+
+2. Passed Validator check for bios resource and bios attribute registry
+*** /redfish/v1/Systems/system/Bios
+INFO - Type (#Bios.v1_1_0.Bios), GET SUCCESS (time: 1.57377)
+INFO - PASS
+*** /redfish/v1/Registries/BiosAttributeRegistry
+INFO - Type (#MessageRegistryFile.v1_1_0.MessageRegistryFile), GET SUCCESS (time: 0.075438)
+INFO - PASS
+INFO -
+*** /redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry
+INFO - Type (#AttributeRegistry.v1_3_2.AttributeRegistry), GET SUCCESS (time: 0.075751)
+INFO - PASS
+
+@odata.id /redfish/v1/Systems/system/Bios odata Exists PASS
+@odata.type #Settings.v1_3_0.Settings odata Exists PASS
+Links [JSON Object] Bios.v1_1_0.Links Yes complex
+Links.ActiveSoftwareImage Link: /redfish/v1/UpdateService/FirmwareInventory/bios_active link to: SoftwareInventory Yes PASS
+Links.SoftwareImages Array (size: 1) array of: SoftwareInventory Yes ...
+Links.SoftwareImages[0] Link: /redfish/v1/UpdateService/FirmwareInventory/bios_active SoftwareInventory Yes PASS
+Links.Oem - Resource.Oem No Optional
+SoftwareImages@odata.count 1 odata Exists PASS
+AttributeRegistry BiosAttributeRegistry string Yes PASS
+Actions [JSON Object] Bios.v1_0_0.Actions Yes complex
+Actions.#Bios.ResetBios Action - Yes PASS
+Actions.#Bios.ChangePassword Action - Yes PASS
+Attributes [JSON Object] Bios.v1_0_0.Attributes Yes complex
+Attributes.attr0 current value primitive Yes PASS
+Id BIOS string Yes PASS
+Description BIOS Configuration Service string Yes PASS
+Name BIOS Configuration string Yes PASS
+Oem - Resource.Oem No Optional
+@Redfish.Settings [JSON Object] Settings.Settings Yes complex
+@Redfish.Settings.MaintenanceWindowResource - link to: ItemOrCollection No Optional
+@Redfish.Settings.SupportedApplyTimes - string (enum) No Optional
+@Redfish.Settings.Time - date No Optional
+@Redfish.Settings.ETag - string No Optional
+@Redfish.Settings.SettingsObject Link: /redfish/v1/Systems/system/Bios/Settings link to: Item Yes PASS
+@Redfish.Settings.Messages - Message No Optional
+
+@odata.id /redfish/v1/Registries/BiosAttributeRegistry odata Exists PASS
+@odata.type #MessageRegistryFile.v1_1_0.MessageRegistryFile odata Exists PASS
+Languages@odata.count 1 odata Exists PASS
+Location@odata.count 1 odata Exists PASS
+Actions - MessageRegistryFile.v1_1_0.Actions No Optional
+Languages Array (size: 1) string Yes ...
+Languages[0] en string Yes PASS
+Registry BiosAttributeRegistry.1.0.0 string Yes PASS
+Location Array (size: 1) array of: Location Yes ...
+Location[0] [JSON Object] Location Yes complex
+Location[0].Language en string Yes PASS
+Location[0].Uri /redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry string Yes PASS
+Location[0].ArchiveUri - string No Optional
+Location[0].PublicationUri - string No Optional
+Location[0].ArchiveFile - string No Optional
+Id BiosAttributeRegistry string Yes PASS
+Description BiosAttributeRegistry Message Registry File Location string Yes PASS
+Name BiosAttributeRegistry Message Registry File string Yes PASS
+Oem - Resource.Oem No Optional
+
+@odata.id /redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry odata Exists PASS
+@odata.type #AttributeRegistry.v1_3_2.AttributeRegistry odata Exists PASS
+Actions - AttributeRegistry.v1_1_0.Actions No Optional
+Language en string Yes PASS
+RegistryVersion 1.0.0 string Yes PASS
+OwningEntity OpenBMC string Yes PASS
+SupportedSystems - SupportedSystems No Optional
+RegistryEntries [JSON Object] AttributeRegistry.v1_0_0.RegistryEntries Yes complex
+RegistryEntries.Attributes Array (size: 1) array of: Attributes Yes ...
+RegistryEntries.Attributes[0] [JSON Object] Attributes Yes complex
+RegistryEntries.Attributes[0].Oem - Resource.Oem No Optional
+RegistryEntries.Attributes[0].ResetRequired - boolean No Optional
+RegistryEntries.Attributes[0].UefiDevicePath - string No Optional
+RegistryEntries.Attributes[0].UefiKeywordName - string No Optional
+RegistryEntries.Attributes[0].UefiNamespaceId - string No Optional
+RegistryEntries.Attributes[0].AttributeName attr0 string Yes PASS
+RegistryEntries.Attributes[0].Type String string (enum) Yes PASS
+RegistryEntries.Attributes[0].Value Array (size: 0) array of: AttributeValue Yes ...
+RegistryEntries.Attributes[0].DisplayName display name for attr0 string Yes PASS
+RegistryEntries.Attributes[0].HelpText description for attr0 string Yes PASS
+RegistryEntries.Attributes[0].WarningText - string No Optional
+RegistryEntries.Attributes[0].CurrentValue current value primitive Yes PASS
+RegistryEntries.Attributes[0].DefaultValue default value primitive Yes PASS
+RegistryEntries.Attributes[0].DisplayOrder - number No Optional
+RegistryEntries.Attributes[0].MenuPath ./menu/path/for/attr0 string Yes PASS
+RegistryEntries.Attributes[0].ReadOnly False boolean Yes PASS
+RegistryEntries.Attributes[0].WriteOnly - boolean No Optional
+RegistryEntries.Attributes[0].GrayOut - boolean No Optional
+RegistryEntries.Attributes[0].Hidden - boolean No Optional
+RegistryEntries.Attributes[0].Immutable - boolean No Optional
+RegistryEntries.Attributes[0].IsSystemUniqueProperty - boolean No Optional
+RegistryEntries.Attributes[0].MaxLength - number No Optional
+RegistryEntries.Attributes[0].MinLength - number No Optional
+RegistryEntries.Attributes[0].ScalarIncrement - number No Optional
+RegistryEntries.Attributes[0].UpperBound - number No Optional
+RegistryEntries.Attributes[0].LowerBound - number No Optional
+RegistryEntries.Attributes[0].ValueExpression - string No Optional
+RegistryEntries.Menus - Menus No Optional
+RegistryEntries.Dependencies - Dependencies No Optional
+Id BiosAttributeRegistry string Yes PASS
+Description - string No Optional
+Name Bios Attribute Registry string Yes PASS
+Oem - Resource.Oem No Optional
+
+Change-Id: Iecc61018c350f0b8c89df59b2864b941508b1916
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Snehalatha Venkatesh <snehalathax.v@intel.com>
+Signed-off-by: Smriti Ayushi <smriti.ayushi@intel.com>
+---
+ redfish-core/include/redfish.hpp | 3 +
+ .../include/registries/bios_registry.hpp | 40 ++
+ redfish-core/lib/bios.hpp | 511 ++++++++++++++++++
+ redfish-core/lib/message_registries.hpp | 10 +-
+ 4 files changed, 563 insertions(+), 1 deletion(-)
+ create mode 100644 redfish-core/include/registries/bios_registry.hpp
+
+diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
+index a9704d6..e4881ff 100644
+--- a/redfish-core/include/redfish.hpp
++++ b/redfish-core/include/redfish.hpp
+@@ -152,7 +152,10 @@ class RedfishService
+ requestRoutesSystemActionsReset(app);
+ requestRoutesSystemResetActionInfo(app);
+ requestRoutesBiosService(app);
++ requestRoutesBiosSettings(app);
++ requestRoutesBiosAttributeRegistry(app);
+ requestRoutesBiosReset(app);
++ requestRoutesBiosChangePassword(app);
+
+ #ifdef BMCWEB_ENABLE_VM_NBDPROXY
+ requestNBDVirtualMediaRoutes(app);
+diff --git a/redfish-core/include/registries/bios_registry.hpp b/redfish-core/include/registries/bios_registry.hpp
+new file mode 100644
+index 0000000..bcf6b73
+--- /dev/null
++++ b/redfish-core/include/registries/bios_registry.hpp
+@@ -0,0 +1,40 @@
++/*
++// Copyright (c) 2020 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++#pragma once
++#include <registries.hpp>
++
++namespace redfish::registries::bios
++{
++const Header header = {
++ "Copyright 2020 OpenBMC. All rights reserved.",
++ "#MessageRegistry.v1_4_0.MessageRegistry",
++ "BiosAttributeRegistry.1.0.0",
++ "Bios Attribute Registry",
++ "en",
++ "This registry defines the messages for bios attribute registry.",
++ "BiosAttributeRegistry",
++ "1.0.0",
++ "OpenBMC",
++};
++// BiosAttributeRegistry registry is not defined in DMTF, We should use
++// OEM defined registries for this purpose.
++// Below link is wrong - We need to define OEM registries and use
++// appropriate data here.
++constexpr const char* url =
++ "https://redfish.dmtf.org/registries/BiosAttributeRegistry.1.0.0.json";
++
++constexpr std::array<MessageEntry, 0> registry = {};
++} // namespace redfish::registries::bios
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index d8475ae..e92e842 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -3,8 +3,140 @@
+ #include <app.hpp>
+ #include <registries/privilege_registry.hpp>
+ #include <utils/fw_utils.hpp>
++
+ namespace redfish
+ {
++
++/*baseBIOSTable
++map{attributeName,struct{attributeType,readonlyStatus,displayname,
++ description,menuPath,current,default,
++ array{struct{optionstring,optionvalue}}}}
++*/
++using BiosBaseTableType = std::vector<std::pair<
++ std::string,
++ std::tuple<
++ std::string, bool, std::string, std::string, std::string,
++ std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
++ std::vector<
++ std::tuple<std::string, std::variant<int64_t, std::string>>>>>>;
++using BiosBaseTableItemType = std::pair<
++ std::string,
++ std::tuple<
++ std::string, bool, std::string, std::string, std::string,
++ std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
++ std::vector<
++ std::tuple<std::string, std::variant<int64_t, std::string>>>>>;
++using OptionsItemType =
++ std::tuple<std::string, std::variant<int64_t, std::string>>;
++
++enum BiosBaseTableIndex
++{
++ biosBaseAttrType = 0,
++ biosBaseReadonlyStatus,
++ biosBaseDisplayName,
++ biosBaseDescription,
++ biosBaseMenuPath,
++ biosBaseCurrValue,
++ biosBaseDefaultValue,
++ biosBaseOptions
++};
++enum OptionsItemIndex
++{
++ optItemType = 0,
++ optItemValue
++};
++/*
++ The Pending attribute name and new value.
++ ex- { {"QuietBoot",Type.Integer, 0x1},
++ { "DdrFreqLimit",Type.String,"2933"}
++ }
++*/
++using PendingAttributesType = std::vector<std::pair<
++ std::string, std::tuple<std::string, std::variant<int64_t, std::string>>>>;
++using PendingAttributesItemType =
++ std::pair<std::string,
++ std::tuple<std::string, std::variant<int64_t, std::string>>>;
++enum PendingAttributesIndex
++{
++ pendingAttrType = 0,
++ pendingAttrValue
++};
++static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
++{
++ std::string ret;
++ if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
++ "AttributeType.Enumeration")
++ {
++ ret = "Enumeration";
++ }
++ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
++ "Manager.AttributeType.String")
++ {
++ ret = "String";
++ }
++ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
++ "Manager.AttributeType.Password")
++ {
++ ret = "Password";
++ }
++ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
++ "Manager.AttributeType.Integer")
++ {
++ ret = "Integer";
++ }
++ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
++ "Manager.AttributeType.Boolean")
++ {
++ ret = "Boolean";
++ }
++ else
++ {
++ ret = "UNKNOWN";
++ }
++
++ return ret;
++}
++static std::string mapBoundTypeToRedfish(const std::string_view typeDbus)
++{
++ std::string ret;
++ if (typeDbus ==
++ "xyz.openbmc_project.BIOSConfig.Manager.BoundType.ScalarIncrement")
++ {
++ ret = "ScalarIncrement";
++ }
++ else if (typeDbus ==
++ "xyz.openbmc_project.BIOSConfig.Manager.BoundType.LowerBound")
++ {
++ ret = "LowerBound";
++ }
++ else if (typeDbus ==
++ "xyz.openbmc_project.BIOSConfig.Manager.BoundType.UpperBound")
++ {
++ ret = "UpperBound";
++ }
++ else if (typeDbus ==
++ "xyz.openbmc_project.BIOSConfig.Manager.BoundType.MinStringLength")
++ {
++ ret = "MinStringLength";
++ }
++ else if (typeDbus ==
++ "xyz.openbmc_project.BIOSConfig.Manager.BoundType.MaxStringLength")
++ {
++ ret = "MaxStringLength";
++ }
++ else if (typeDbus ==
++ "xyz.openbmc_project.BIOSConfig.Manager.BoundType.OneOf")
++ {
++ ret = "OneOf";
++ }
++ else
++ {
++ ret = "UNKNOWN";
++ }
++
++ return ret;
++}
++
+ /**
+ * BiosService class supports handle get method for bios.
+ */
+@@ -23,6 +155,85 @@ inline void
+ // Get the ActiveSoftwareImage and SoftwareImages
+ fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose, "",
+ true);
++
++ asyncResp->res.jsonValue["@Redfish.Settings"] = {
++ {"@odata.type", "#Settings.v1_3_0.Settings"},
++ {"SettingsObject",
++ {{"@odata.id", "/redfish/v1/Systems/system/Bios/Settings"}}}};
++ asyncResp->res.jsonValue["AttributeRegistry"] = "BiosAttributeRegistry";
++ asyncResp->res.jsonValue["Attributes"] = nlohmann::json::object();
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
++ << ec;
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++ const std::string& service = getObjectType.begin()->first;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](
++ const boost::system::error_code ec,
++ const std::variant<BiosBaseTableType>& retBiosTable) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "getBiosAttributes DBUS error: "
++ << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ const BiosBaseTableType* baseBiosTable =
++ std::get_if<BiosBaseTableType>(&retBiosTable);
++ nlohmann::json& attributesJson =
++ asyncResp->res.jsonValue["Attributes"];
++ if (baseBiosTable == nullptr)
++ {
++ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ for (const BiosBaseTableItemType& item : *baseBiosTable)
++ {
++ const std::string& key = item.first;
++ const std::string& itemType =
++ std::get<biosBaseAttrType>(item.second);
++ std::string attrType = mapAttrTypeToRedfish(itemType);
++ if (attrType == "String")
++ {
++ const std::string* currValue =
++ std::get_if<std::string>(
++ &std::get<biosBaseCurrValue>(item.second));
++ attributesJson.emplace(
++ key, currValue != nullptr ? *currValue : "");
++ }
++ else if (attrType == "Integer")
++ {
++ const int64_t* currValue = std::get_if<int64_t>(
++ &std::get<biosBaseCurrValue>(item.second));
++ attributesJson.emplace(
++ key, currValue != nullptr ? *currValue : 0);
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "Unsupported attribute type.";
++ messages::internalError(asyncResp->res);
++ }
++ }
++ },
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.BIOSConfig.Manager", "BaseBIOSTable");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
+ }
+ inline void requestRoutesBiosService(App& app)
+ {
+@@ -31,6 +242,306 @@ inline void requestRoutesBiosService(App& app)
+ .methods(boost::beast::http::verb::get)(handleBiosServiceGet);
+ }
+
++/**
++ * BiosSettings class supports handle GET/PATCH method for
++ * BIOS configuration pending settings.
++ */
++inline void requestRoutesBiosSettings(App& app)
++{
++ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings")
++ .privileges(redfish::privileges::getBios)
++ .methods(boost::beast::http::verb::get)(
++ [](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ asyncResp->res.jsonValue["@odata.id"] =
++ asyncResp->res.jsonValue["@odata.id"] =
++ "/redfish/v1/Systems/system/Bios/Settings";
++ asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
++ asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1";
++ asyncResp->res.jsonValue["Id"] = "BiosSettingsV1";
++ asyncResp->res.jsonValue["AttributeRegistry"] =
++ "BiosAttributeRegistry";
++ asyncResp->res.jsonValue["Attributes"] = {};
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "ObjectMapper::GetObject call failed: "
++ << ec;
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++ std::string service = getObjectType.begin()->first;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](
++ const boost::system::error_code ec,
++ const std::variant<PendingAttributesType>&
++ retPendingAttributes) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "getBiosSettings DBUS error: " << ec;
++ messages::resourceNotFound(
++ asyncResp->res, "Systems/system/Bios",
++ "Settings");
++ return;
++ }
++ const PendingAttributesType* pendingAttributes =
++ std::get_if<PendingAttributesType>(
++ &retPendingAttributes);
++ nlohmann::json& attributesJson =
++ asyncResp->res.jsonValue["Attributes"];
++ if (pendingAttributes == nullptr)
++ {
++ BMCWEB_LOG_ERROR
++ << "pendingAttributes == nullptr ";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ for (const PendingAttributesItemType& item :
++ *pendingAttributes)
++ {
++ const std::string& key = item.first;
++ const std::string& itemType =
++ std::get<pendingAttrType>(item.second);
++ std::string attrType =
++ mapAttrTypeToRedfish(itemType);
++ if (attrType == "String")
++ {
++ const std::string* currValue =
++ std::get_if<std::string>(
++ &std::get<pendingAttrValue>(
++ item.second));
++ attributesJson.emplace(
++ key, currValue != nullptr
++ ? *currValue
++ : "");
++ }
++ else if (attrType == "Integer")
++ {
++ const int64_t* currValue =
++ std::get_if<int64_t>(
++ &std::get<pendingAttrValue>(
++ item.second));
++ attributesJson.emplace(
++ key, currValue != nullptr
++ ? *currValue
++ : 0);
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR
++ << "Unsupported attribute type.";
++ messages::internalError(asyncResp->res);
++ }
++ }
++ },
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "PendingAttributes");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
++ });
++}
++/**
++ * BiosAttributeRegistry class supports handle get method for BIOS attribute
++ * registry.
++ */
++inline void requestRoutesBiosAttributeRegistry(App& app)
++{
++ BMCWEB_ROUTE(
++ app,
++ "/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry/")
++ .privileges(redfish::privileges::getBios)
++ .methods(
++ boost::beast::http::verb::
++ get)([](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ asyncResp->res.jsonValue["@odata.id"] =
++ "/redfish/v1/Registries/BiosAttributeRegistry/"
++ "BiosAttributeRegistry";
++ asyncResp->res.jsonValue["@odata.type"] =
++ "#AttributeRegistry.v1_3_2.AttributeRegistry";
++ asyncResp->res.jsonValue["Name"] = "Bios Attribute Registry";
++ asyncResp->res.jsonValue["Id"] = "BiosAttributeRegistry";
++ asyncResp->res.jsonValue["RegistryVersion"] = "1.0.0";
++ asyncResp->res.jsonValue["Language"] = "en";
++ asyncResp->res.jsonValue["OwningEntity"] = "OpenBMC";
++ asyncResp->res.jsonValue["RegistryEntries"]["Attributes"] =
++ nlohmann::json::array();
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "ObjectMapper::GetObject call failed: " << ec;
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++ std::string service = getObjectType.begin()->first;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const std::variant<BiosBaseTableType>&
++ retBiosTable) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "getBiosAttributeRegistry DBUS error: "
++ << ec;
++ messages::resourceNotFound(
++ asyncResp->res, "Registries/Bios", "Bios");
++ return;
++ }
++ const BiosBaseTableType* baseBiosTable =
++ std::get_if<BiosBaseTableType>(&retBiosTable);
++ nlohmann::json& attributeArray =
++ asyncResp->res
++ .jsonValue["RegistryEntries"]["Attributes"];
++ nlohmann::json optionsArray =
++ nlohmann::json::array();
++ if (baseBiosTable == nullptr)
++ {
++ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ for (const BiosBaseTableItemType& item :
++ *baseBiosTable)
++ {
++ const std::string& itemType =
++ std::get<biosBaseAttrType>(item.second);
++ std::string attrType =
++ mapAttrTypeToRedfish(itemType);
++ if (attrType == "UNKNOWN")
++ {
++ BMCWEB_LOG_ERROR << "attrType == UNKNOWN";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ nlohmann::json attributeItem;
++ attributeItem["AttributeName"] = item.first;
++ attributeItem["Type"] = attrType;
++ attributeItem["ReadOnly"] =
++ std::get<biosBaseReadonlyStatus>(
++ item.second);
++ attributeItem["DisplayName"] =
++ std::get<biosBaseDisplayName>(item.second);
++ attributeItem["HelpText"] =
++ std::get<biosBaseDescription>(item.second);
++ attributeItem["MenuPath"] =
++ std::get<biosBaseMenuPath>(item.second);
++
++ if (attrType == "String")
++ {
++ const std::string* currValue =
++ std::get_if<std::string>(
++ &std::get<biosBaseCurrValue>(
++ item.second));
++ const std::string* defValue =
++ std::get_if<std::string>(
++ &std::get<biosBaseDefaultValue>(
++ item.second));
++ attributeItem["CurrentValue"] =
++ currValue != nullptr ? *currValue : "";
++ attributeItem["DefaultValue"] =
++ defValue != nullptr ? *defValue : "";
++ }
++ else if (attrType == "Integer")
++ {
++ const int64_t* currValue =
++ std::get_if<int64_t>(
++ &std::get<biosBaseCurrValue>(
++ item.second));
++ const int64_t* defValue =
++ std::get_if<int64_t>(
++ &std::get<biosBaseDefaultValue>(
++ item.second));
++ attributeItem["CurrentValue"] =
++ currValue != nullptr ? *currValue : 0;
++ attributeItem["DefaultValue"] =
++ defValue != nullptr ? *defValue : 0;
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR
++ << "Unsupported attribute type.";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const std::vector<OptionsItemType>&
++ optionsVector =
++ std::get<biosBaseOptions>(item.second);
++ for (const OptionsItemType& optItem :
++ optionsVector)
++ {
++ nlohmann::json optItemJson;
++ const std::string& strOptItemType =
++ std::get<optItemType>(optItem);
++ std::string optItemTypeRedfish =
++ mapBoundTypeToRedfish(strOptItemType);
++ if (optItemTypeRedfish == "UNKNOWN")
++ {
++ BMCWEB_LOG_ERROR
++ << "optItemTypeRedfish == UNKNOWN";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ if (optItemTypeRedfish == "OneOf")
++ {
++ const std::string* currValue =
++ std::get_if<std::string>(
++ &std::get<optItemValue>(
++ optItem));
++ optItemJson[optItemTypeRedfish] =
++ currValue != nullptr ? *currValue
++ : "";
++ }
++ else
++ {
++ const int64_t* currValue =
++ std::get_if<int64_t>(
++ &std::get<optItemValue>(
++ optItem));
++ optItemJson[optItemTypeRedfish] =
++ currValue != nullptr ? *currValue
++ : 0;
++ }
++
++ optionsArray.push_back(optItemJson);
++ }
++
++ attributeItem["Value"] = optionsArray;
++ attributeArray.push_back(attributeItem);
++ }
++ },
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "BaseBIOSTable");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
++ });
++}
++
+ /**
+ * BiosReset class supports handle POST method for Reset bios.
+ * The class retrieves and sends data directly to D-Bus.
+diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp
+index c030e5a..d76f70b 100644
+--- a/redfish-core/lib/message_registries.hpp
++++ b/redfish-core/lib/message_registries.hpp
+@@ -17,6 +17,7 @@
+
+ #include "registries.hpp"
+ #include "registries/base_message_registry.hpp"
++#include "registries/bios_registry.hpp"
+ #include "registries/openbmc_message_registry.hpp"
+ #include "registries/resource_event_message_registry.hpp"
+ #include "registries/task_event_message_registry.hpp"
+@@ -128,7 +129,6 @@ inline void handleMessageRegistryGet(
+ const crow::Request& /*req*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& registry, const std::string& registryMatch)
+-
+ {
+ const registries::Header* header = nullptr;
+ std::vector<const registries::MessageEntry*> registryEntries;
+@@ -167,6 +167,14 @@ inline void handleMessageRegistryGet(
+ registryEntries.emplace_back(&entry);
+ }
+ }
++ else if (registry == "BiosAttributeRegistry")
++ {
++ header = &registries::bios::header;
++ for (const registries::MessageEntry& entry : registries::bios::registry)
++ {
++ registryEntries.emplace_back(&entry);
++ }
++ }
+ else
+ {
+ messages::resourceNotFound(
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch
new file mode 100644
index 000000000..a52a1614f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch
@@ -0,0 +1,148 @@
+From ffa924ef204930a5bb442bf654eac02543acfb8f Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Wed, 30 Jun 2021 15:18:46 +0000
+Subject: [PATCH 2/5] BaseBiosTable: Add support for PATCH operation
+
+This commit brings in support for PATCH operation of the
+bios variables that updates the BaseBiosTable.
+
+Tested-By:
+* Passed Redfish validator
+
+* Single Attribute:
+PATCH https://${bmc}/redfish/v1/Systems/system/Bios/Settings -d
+'{"data":[{"AttributeName": <attribute name>, "AttributeType":
+<attribute type>, "AttributeValue": <attribute value>}]}'
+
+* Multiple Attributes:
+PATCH https://${bmc}/redfish/v1/Systems/system/Bios/Settings -d
+'{"data":[{"AttributeName": <attribute name>, "AttributeType":
+<attribute type>, "AttributeValue": <attribute value>},
+{"AttributeName": <attribute name>, "AttributeType":
+<attribute type>, "AttributeValue": <attribute value>}]}'
+
+This makes use of the "Set" of "PendingAttributes" in the
+backend and that updates the BaseBiosTable.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Change-Id: I12e78e5ac623c264c7a3e1dd5198aca67172736d
+---
+ redfish-core/lib/bios.hpp | 95 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 95 insertions(+)
+
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index c1a5c56..14d2171 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -96,6 +96,29 @@ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
+
+ return ret;
+ }
++static std::string mapRedfishToAttrType(const std::string_view type)
++{
++ std::string ret;
++ if (type == "string")
++ {
++ ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String";
++ }
++ else if (type == "int")
++ {
++ ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer";
++ }
++ else if (type == "enum")
++ {
++ ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType."
++ "Enumeration";
++ }
++ else
++ {
++ ret = "UNKNOWN";
++ }
++
++ return ret;
++}
+ static std::string mapBoundTypeToRedfish(const std::string_view typeDbus)
+ {
+ std::string ret;
+@@ -370,6 +393,78 @@ inline void requestRoutesBiosSettings(App& app)
+ "/xyz/openbmc_project/bios_config/manager",
+ std::array<const char*, 0>());
+ });
++
++ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings")
++ .privileges({{"ConfigureComponents"}})
++ .methods(boost::beast::http::verb::patch)(
++ [](const crow::Request& req,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ nlohmann::json inpJson;
++
++ if (!redfish::json_util::readJsonPatch(req, asyncResp->res, "data",
++ inpJson))
++ {
++ return;
++ }
++
++ for (auto& attrInfo : inpJson)
++ {
++ std::optional<std::string> attrName;
++ std::optional<std::string> attrType;
++ std::optional<std::string> attrValue;
++ if (!json_util::getValueFromJsonObject(
++ attrInfo, "AttributeName", attrName))
++ {
++ messages::propertyMissing(asyncResp->res,
++ "AttributeName");
++ return;
++ }
++ if (!json_util::getValueFromJsonObject(
++ attrInfo, "AttributeType", attrType))
++ {
++ messages::propertyMissing(asyncResp->res,
++ "AttributeType");
++ return;
++ }
++ if (!json_util::getValueFromJsonObject(
++ attrInfo, "AttributeValue", attrValue))
++ {
++ messages::propertyMissing(asyncResp->res,
++ "AttributeValue");
++ return;
++ }
++ std::string biosAttrType = mapRedfishToAttrType(*attrType);
++
++ if (biosAttrType == "UNKNOWN")
++ {
++ BMCWEB_LOG_ERROR << "Invalid attribute type";
++ messages::propertyValueNotInList(
++ asyncResp->res, "AttributeType", *attrType);
++ return;
++ }
++
++ PendingAttributesType pendingAttributes;
++ pendingAttributes.emplace_back(std::make_pair(
++ *attrName, std::make_tuple(biosAttrType, *attrValue)));
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "doPatch resp_handler got error " << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ },
++ "xyz.openbmc_project.BIOSConfigManager",
++ "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Set",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "PendingAttributes",
++ std::variant<PendingAttributesType>(pendingAttributes));
++ }
++ });
+ }
+ /**
+ * BiosAttributeRegistry class supports handle get method for BIOS attribute
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch
new file mode 100644
index 000000000..5ed92cc3e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch
@@ -0,0 +1,53 @@
+From b7adca60dd69ac9566dc8f417065e244198fc711 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 6 Oct 2021 22:27:20 +0000
+Subject: [PATCH] Add support to ResetBios action
+
+Tested:
+
+Bios reset flag can be modified throw redfish
+POST https://IP_ADDR/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios
+
+Change-Id: Ic719c55705e5f634539b3dd858b60922e505a8d0
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/lib/bios.hpp | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index f5aa7b7..f613613 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -648,17 +648,23 @@ inline void
+ handleBiosResetPost(const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+ {
++ std::string resetFlag =
++ "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.FactoryDefaults";
++
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+- BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec;
++ BMCWEB_LOG_ERROR << "doPost bios reset got error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+- "org.open_power.Software.Host.Updater", "/xyz/openbmc_project/software",
+- "xyz.openbmc_project.Common.FactoryReset", "Reset");
++ "xyz.openbmc_project.BIOSConfigManager",
++ "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Set",
++ "xyz.openbmc_project.BIOSConfig.Manager", "ResetBIOSSettings",
++ std::variant<std::string>(resetFlag));
+ }
+
+ inline void requestRoutesBiosReset(App& app)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch
new file mode 100644
index 000000000..de705b60b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch
@@ -0,0 +1,117 @@
+From 22956921a228f6f1cbbbd3045a3cc3969732dca3 Mon Sep 17 00:00:00 2001
+From: Arun Lal K M <arun.lal@intel.com>
+Date: Fri, 8 Oct 2021 20:56:00 +0000
+Subject: [PATCH] Add support to ChangePassword action
+
+Tested:
+
+Passed Redfish validator.
+Bios change password:
+root@intel-obmc:~# cat /var/lib/bios-settings-manager/seedData
+{
+"UserPwdHash": "08D91157785366CDC3AA64D87E5E3C621EDAB13E26B6E484397EBA5E459E54C567BF5B1FFB36A43B6142B18F8D642E9D",
+"AdminPwdHash": "08D91157785366CDC3AA64D87E5E3C621EDAB13E26B6E484397EBA5E459E54C567BF5B1FFB36A43B6142B18F8D642E9D",
+"Seed": "123456",
+"HashAlgo": "SHA384"
+}
+POST https://IP_ADDR/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword
+{
+ "NewPassword": "12345678",
+ "OldPassword": "1234567890",
+ "PasswordName": "Administrator"
+}
+root@intel-obmc:~# cat /var/lib/bios-settings-manager/passwordData
+{
+ "CurrentPassword": "1234567890",
+ "IsAdminPwdChanged": 1,
+ "IsUserPwdChanged": 0,
+ "NewPassword": "2DD65D57EB60B1D92C5F3D2DC84724FCEE7BC02E57AA75E834712266ED94CAC704047B2FF7CEC1C36BED280B36BB5AC6",
+ "UserName": "Administrator"
+}
+
+Signed-off-by: Arun Lal K M <arun.lal@intel.com>
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ redfish-core/lib/bios.hpp | 59 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index f613613..b06a904 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -175,6 +175,10 @@ inline void
+ asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = {
+ {"target", "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}};
+
++ asyncResp->res.jsonValue["Actions"]["#Bios.ChangePassword"] = {
++ {"target", "/redfish/v1/Systems/system/Bios/Actions/"
++ "Bios.ChangePassword"}};
++
+ // Get the ActiveSoftwareImage and SoftwareImages
+ fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose, "",
+ true);
+@@ -265,6 +269,61 @@ inline void requestRoutesBiosService(App& app)
+ .methods(boost::beast::http::verb::get)(handleBiosServiceGet);
+ }
+
++/**
++ * BiosChangePassword class supports handle POST method for change bios
++ * password. The class retrieves and sends data directly to D-Bus.
++ */
++inline void requestRoutesBiosChangePassword(App& app)
++{
++ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/")
++ .privileges({{"ConfigureComponents"}})
++ .methods(boost::beast::http::verb::post)(
++ [](const crow::Request& req,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ std::string currentPassword, newPassword, userName;
++ if (!json_util::readJsonPatch(req, asyncResp->res, "NewPassword",
++ newPassword, "OldPassword",
++ currentPassword, "PasswordName",
++ userName))
++ {
++ return;
++ }
++ if (currentPassword.empty())
++ {
++ messages::actionParameterUnknown(
++ asyncResp->res, "ChangePassword", "OldPassword");
++ return;
++ }
++ if (newPassword.empty())
++ {
++ messages::actionParameterUnknown(
++ asyncResp->res, "ChangePassword", "NewPassword");
++ return;
++ }
++ if (userName.empty())
++ {
++ messages::actionParameterUnknown(
++ asyncResp->res, "ChangePassword", "PasswordName");
++ return;
++ }
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_CRITICAL
++ << "Failed in doPost(BiosChangePassword) "
++ << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ },
++ "xyz.openbmc_project.BIOSConfigPassword",
++ "/xyz/openbmc_project/bios_config/password",
++ "xyz.openbmc_project.BIOSConfig.Password", "ChangePassword",
++ userName, currentPassword, newPassword);
++ });
++}
++
+ /**
+ * BiosSettings class supports handle GET/PATCH method for
+ * BIOS configuration pending settings.
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch
new file mode 100644
index 000000000..26393bfee
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch
@@ -0,0 +1,46 @@
+From edc6925e8c0d9f60da1f70c524261efaf05b2710 Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Wed, 30 Jun 2021 15:42:06 +0000
+Subject: [PATCH 5/5] Fix:remove bios user pwd change option via Redfish
+
+BMC should not provide user bios setup password change option via
+Redfish as per bios security requirements. Only Admin BIOS setup
+password is supported.
+
+Added check for the password name action parameter and
+do not allow if it has User Password value from redfish side.
+
+Tested: sent POST query in redfish on URI:
+https://<ip>/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword
+error occurs for UserPassword parameter and allows for AdminPassword.
+
+Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com>
+Change-Id: I169cc6a4f786625d9e8b8dfe56816d52b1740f4c
+---
+ redfish-core/lib/bios.hpp | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index 0250c59..360a749 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -323,6 +323,16 @@ inline void requestRoutesBiosChangePassword(App& app)
+ asyncResp->res, "ChangePassword", "PasswordName");
+ return;
+ }
++
++ // In Intel BIOS, we are not supporting user password in BIOS
++ // setup
++ if (userName == "UserPassword")
++ {
++ messages::actionParameterUnknown(
++ asyncResp->res, "ChangePassword", "PasswordName");
++ return;
++ }
++
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch
new file mode 100644
index 000000000..05257bbf7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch
@@ -0,0 +1,963 @@
+From bedec07809e2d2ecfed9db0d9509d2380ea094b7 Mon Sep 17 00:00:00 2001
+From: Arun Lal K M <arun.lal@intel.com>
+Date: Wed, 19 Jan 2022 14:44:07 +0000
+Subject: [PATCH] Add fix for broken feature 'Pending Attributes'.
+
+Fix is added for the following:
+1) GET to 'redfish/v1/Systems/system/Bios'.
+2) PATCH to 'redfish/v1/Systems/system/Bios/Settings'.
+3) GET to 'redfish/v1/Systems/system/Bios/Settings'.
+4) Fix for incremental duplicate values in BiosAttributeRegistry.
+5) POST to '/redfish/v1/Systems/system/Bios/Actions
+ /Bios.ChangePassword/'.
+6) Add support for Enumeration.
+7) Support DMTF standard of displaying "Value" in BIOS attribute registries.
+
+Tested:
+By giving PATCH to 'redfish/v1/Systems/system/Bios/Settings'
+PATCH command raw data:
+{
+ "data":{
+ "AmpPrefetchEnable": "0x1",
+ "Ce2LmLoggingEn": "0x1",
+ "DfxEadrDebugLogs": "0x2",
+ "PsfUrEnable": "0x1",
+ "ATS": "0x0"
+ }
+}
+
+Response:
+{
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "#Message.v1_1_1.Message",
+ "Message": "Successfully Completed Request",
+ "MessageArgs": [],
+ "MessageId": "Base.1.8.1.Success",
+ "MessageSeverity": "OK",
+ "Resolution": "None"
+ }
+ ]
+}
+
+By giving GET to 'redfish/v1/Systems/system/Bios'
+Response:
+{
+ "@Redfish.Settings": {
+ "@odata.type": "#Settings.v1_3_0.Settings",
+ "SettingsObject": {
+ "@odata.id":
+ "/redfish/v1/Systems/system/Bios/Settings"
+ }
+ },
+ "@odata.id": "/redfish/v1/Systems/system/Bios",
+ "@odata.type": "#Bios.v1_1_0.Bios",
+ "Actions": {
+ "#Bios.ChangePassword": {
+ "target":
+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword"
+ },
+ "#Bios.ResetBios": {
+ "target":
+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"
+ }
+ },
+ "AttributeRegistry": "BiosAttributeRegistry",
+ "Attributes": {
+ "AEPErrorInjEn": "0x00",
+ "ARIEnable": "0x01",
+ "ARIForward": "0x00",
+ ...
+ ...
+ ...
+ "txEqCalibration": "0x01",
+ "volMemMode": "0x00",
+ "wrVrefCenter": "0x01"
+ },
+ "Description": "BIOS Configuration Service",
+ "Id": "BIOS",
+ "Links": {
+ "ActiveSoftwareImage": {
+ "@odata.id":
+ "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
+ },
+ "SoftwareImages": [
+ {
+ "@odata.id":
+ "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
+ }
+ ],
+ "SoftwareImages@odata.count": 1
+ },
+ "Name": "BIOS Configuration"
+}
+
+By giving GET to 'redfish/v1/Systems/system/Bios/Settings'
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/Bios/Settings",
+ "@odata.type": "#Bios.v1_1_0.Bios",
+ "AttributeRegistry": "BiosAttributeRegistry",
+ "Attributes": {
+ "ATS": "0x0",
+ "AmpPrefetchEnable": "0x1",
+ "Ce2LmLoggingEn": "0x1",
+ "DfxEadrDebugLogs": "0x2",
+ "PsfUrEnable": "0x1"
+ },
+ "Id": "BiosSettingsV1",
+ "Name": "Bios Settings Version 1"
+}
+
+By giving POST to '/redfish/v1/Systems/system/Bios/Actions
+/Bios.ChangePassword/'
+Response: Success
+
+By running Redfish-Service-Validator
+Result:
+Elapsed time: 0:09:36
+invalidPropertyValue: 108
+metadataNamespaces: 2185
+missingNamespaces: 1
+optionalAction: 9
+pass: 13772
+passAction: 22
+passGet: 541
+reflink: 1
+repeat: 47
+serviceNamespaces: 75
+skipOptional: 9276
+unverifiedComplexAdditional: 1
+warnDeprecated: 230
+warningPresent: 54
+Validation has succeeded.
+
+Signed-off-by: Arun Lal K M <arun.lal@intel.com>
+Signed-off-by: Snehalatha Venkatesh <snehalathax.v@intel.com>
+---
+ redfish-core/lib/bios.hpp | 605 +++++++++++++++++++++++++-------------
+ 1 file changed, 394 insertions(+), 211 deletions(-)
+
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index bbf9460..c3192dd 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -12,13 +12,15 @@ map{attributeName,struct{attributeType,readonlyStatus,displayname,
+ description,menuPath,current,default,
+ array{struct{optionstring,optionvalue}}}}
+ */
+-using BiosBaseTableType = std::vector<std::pair<
++
++using BiosBaseTableType = boost::container::flat_map<
+ std::string,
+ std::tuple<
+ std::string, bool, std::string, std::string, std::string,
+ std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
+ std::vector<
+- std::tuple<std::string, std::variant<int64_t, std::string>>>>>>;
++ std::tuple<std::string, std::variant<int64_t, std::string>>>>>;
++
+ using BiosBaseTableItemType = std::pair<
+ std::string,
+ std::tuple<
+@@ -29,6 +31,13 @@ using BiosBaseTableItemType = std::pair<
+ using OptionsItemType =
+ std::tuple<std::string, std::variant<int64_t, std::string>>;
+
++using PendingAttributesType = boost::container::flat_map<
++ std::string, std::tuple<std::string, std::variant<int64_t, std::string>>>;
++
++using PendingAttributesItemType =
++ std::pair<std::string,
++ std::tuple<std::string, std::variant<int64_t, std::string>>>;
++
+ enum BiosBaseTableIndex
+ {
+ biosBaseAttrType = 0,
+@@ -45,17 +54,7 @@ enum OptionsItemIndex
+ optItemType = 0,
+ optItemValue
+ };
+-/*
+- The Pending attribute name and new value.
+- ex- { {"QuietBoot",Type.Integer, 0x1},
+- { "DdrFreqLimit",Type.String,"2933"}
+- }
+-*/
+-using PendingAttributesType = std::vector<std::pair<
+- std::string, std::tuple<std::string, std::variant<int64_t, std::string>>>>;
+-using PendingAttributesItemType =
+- std::pair<std::string,
+- std::tuple<std::string, std::variant<int64_t, std::string>>>;
++
+ enum PendingAttributesIndex
+ {
+ pendingAttrType = 0,
+@@ -64,30 +63,20 @@ enum PendingAttributesIndex
+ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
+ {
+ std::string ret;
+- if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
+- "AttributeType.Enumeration")
+- {
+- ret = "Enumeration";
+- }
+- else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+- "Manager.AttributeType.String")
++ if (typeDbus == "xyz.openbmc_project.BIOSConfig."
++ "Manager.AttributeType.String")
+ {
+ ret = "String";
+ }
+- else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+- "Manager.AttributeType.Password")
+- {
+- ret = "Password";
+- }
+ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+ "Manager.AttributeType.Integer")
+ {
+ ret = "Integer";
+ }
+ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+- "Manager.AttributeType.Boolean")
++ "Manager.AttributeType.Enumeration")
+ {
+- ret = "Boolean";
++ ret = "Enumeration";
+ }
+ else
+ {
+@@ -96,29 +85,7 @@ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
+
+ return ret;
+ }
+-static std::string mapRedfishToAttrType(const std::string_view type)
+-{
+- std::string ret;
+- if (type == "string")
+- {
+- ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String";
+- }
+- else if (type == "int")
+- {
+- ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer";
+- }
+- else if (type == "enum")
+- {
+- ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType."
+- "Enumeration";
+- }
+- else
+- {
+- ret = "UNKNOWN";
+- }
+
+- return ret;
+-}
+ static std::string mapBoundTypeToRedfish(const std::string_view typeDbus)
+ {
+ std::string ret;
+@@ -201,6 +168,15 @@ inline void
+
+ return;
+ }
++
++ if (getObjectType.empty())
++ {
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++
+ const std::string& service = getObjectType.begin()->first;
+
+ crow::connections::systemBus->async_method_call(
+@@ -220,7 +196,7 @@ inline void
+ asyncResp->res.jsonValue["Attributes"];
+ if (baseBiosTable == nullptr)
+ {
+- BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
++ BMCWEB_LOG_ERROR << "baseBiosTable is empty";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+@@ -230,7 +206,7 @@ inline void
+ const std::string& itemType =
+ std::get<biosBaseAttrType>(item.second);
+ std::string attrType = mapAttrTypeToRedfish(itemType);
+- if (attrType == "String")
++ if (attrType == "String" || attrType == "Enumeration")
+ {
+ const std::string* currValue =
+ std::get_if<std::string>(
+@@ -248,7 +224,6 @@ inline void
+ else
+ {
+ BMCWEB_LOG_ERROR << "Unsupported attribute type.";
+- messages::internalError(asyncResp->res);
+ }
+ }
+ },
+@@ -275,8 +250,9 @@ inline void requestRoutesBiosService(App& app)
+ */
+ inline void requestRoutesBiosChangePassword(App& app)
+ {
+- BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/")
+- .privileges({{"ConfigureComponents"}})
++ BMCWEB_ROUTE(app,
++ "/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword/")
++ .privileges(redfish::privileges::postBios)
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+@@ -342,180 +318,303 @@ inline void requestRoutesBiosSettings(App& app)
+ {
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings")
+ .privileges(redfish::privileges::getBios)
+- .methods(boost::beast::http::verb::get)(
+- [](const crow::Request&,
+- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+- asyncResp->res.jsonValue["@odata.id"] =
+- asyncResp->res.jsonValue["@odata.id"] =
+- "/redfish/v1/Systems/system/Bios/Settings";
+- asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
+- asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1";
+- asyncResp->res.jsonValue["Id"] = "BiosSettingsV1";
+- asyncResp->res.jsonValue["AttributeRegistry"] =
+- "BiosAttributeRegistry";
+- asyncResp->res.jsonValue["Attributes"] = {};
++ .methods(
++ boost::beast::http::verb::
++ get)([](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ asyncResp->res.jsonValue["@odata.id"] =
++ "/redfish/v1/Systems/system/Bios/Settings";
++ asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
++ asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1";
++ asyncResp->res.jsonValue["Id"] = "BiosSettingsV1";
++ asyncResp->res.jsonValue["AttributeRegistry"] =
++ "BiosAttributeRegistry";
++ asyncResp->res.jsonValue["Attributes"] = {};
+
+- crow::connections::systemBus->async_method_call(
+- [asyncResp](const boost::system::error_code ec,
+- const GetObjectType& getObjectType) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR
+- << "ObjectMapper::GetObject call failed: "
+- << ec;
+- messages::internalError(asyncResp->res);
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "ObjectMapper::GetObject call failed: " << ec;
++ messages::internalError(asyncResp->res);
+
+- return;
+- }
+- std::string service = getObjectType.begin()->first;
+-
+- crow::connections::systemBus->async_method_call(
+- [asyncResp](
+- const boost::system::error_code ec,
+- const std::variant<PendingAttributesType>&
+- retPendingAttributes) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR
+- << "getBiosSettings DBUS error: " << ec;
+- messages::resourceNotFound(
+- asyncResp->res, "Systems/system/Bios",
+- "Settings");
+- return;
+- }
+- const PendingAttributesType* pendingAttributes =
+- std::get_if<PendingAttributesType>(
+- &retPendingAttributes);
+- nlohmann::json& attributesJson =
+- asyncResp->res.jsonValue["Attributes"];
+- if (pendingAttributes == nullptr)
+- {
+- BMCWEB_LOG_ERROR
+- << "pendingAttributes == nullptr ";
+- messages::internalError(asyncResp->res);
+- return;
+- }
+- for (const PendingAttributesItemType& item :
+- *pendingAttributes)
++ return;
++ }
++
++ if (getObjectType.empty())
++ {
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++
++ std::string service = getObjectType.begin()->first;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const std::variant<PendingAttributesType>&
++ retPendingAttributes) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "getBiosSettings DBUS error: " << ec;
++ messages::resourceNotFound(
++ asyncResp->res, "Systems/system/Bios",
++ "Settings");
++ return;
++ }
++
++ const PendingAttributesType* pendingAttributes =
++ std::get_if<PendingAttributesType>(
++ &retPendingAttributes);
++ nlohmann::json& attributesJson =
++ asyncResp->res.jsonValue["Attributes"];
++ if (pendingAttributes == nullptr)
++ {
++ BMCWEB_LOG_ERROR
++ << "pendingAttributes is empty";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ for (const PendingAttributesItemType&
++ pendingAttributesItem : *pendingAttributes)
++ {
++ const std::string& biosAttrType =
++ std::get<pendingAttrType>(
++ pendingAttributesItem.second);
++
++ std::string itemType =
++ mapAttrTypeToRedfish(biosAttrType);
++
++ if (itemType == "String" ||
++ itemType == "Enumeration")
+ {
+- const std::string& key = item.first;
+- const std::string& itemType =
+- std::get<pendingAttrType>(item.second);
+- std::string attrType =
+- mapAttrTypeToRedfish(itemType);
+- if (attrType == "String")
+- {
+- const std::string* currValue =
+- std::get_if<std::string>(
+- &std::get<pendingAttrValue>(
+- item.second));
+- attributesJson.emplace(
+- key, currValue != nullptr
+- ? *currValue
+- : "");
+- }
+- else if (attrType == "Integer")
++ const std::string* currValue =
++ std::get_if<std::string>(
++ &std::get<pendingAttrValue>(
++ pendingAttributesItem.second));
++
++ if (!currValue)
+ {
+- const int64_t* currValue =
+- std::get_if<int64_t>(
+- &std::get<pendingAttrValue>(
+- item.second));
+- attributesJson.emplace(
+- key, currValue != nullptr
+- ? *currValue
+- : 0);
++ BMCWEB_LOG_ERROR
++ << "No string data in pending "
++ "attributes item data";
++ messages::internalError(asyncResp->res);
++ return;
+ }
+- else
++
++ attributesJson.emplace(
++ pendingAttributesItem.first,
++ *currValue);
++ }
++ else if (itemType == "Integer")
++ {
++ const int64_t* currValue =
++ std::get_if<int64_t>(
++ &std::get<pendingAttrValue>(
++ pendingAttributesItem.second));
++
++ if (!currValue)
+ {
+ BMCWEB_LOG_ERROR
+- << "Unsupported attribute type.";
++ << "No int64_t data in pending "
++ "attributes item data";
+ messages::internalError(asyncResp->res);
++ return;
+ }
++
++ attributesJson.emplace(
++ pendingAttributesItem.first,
++ *currValue);
+ }
+- },
+- service, "/xyz/openbmc_project/bios_config/manager",
+- "org.freedesktop.DBus.Properties", "Get",
+- "xyz.openbmc_project.BIOSConfig.Manager",
+- "PendingAttributes");
+- },
+- "xyz.openbmc_project.ObjectMapper",
+- "/xyz/openbmc_project/object_mapper",
+- "xyz.openbmc_project.ObjectMapper", "GetObject",
+- "/xyz/openbmc_project/bios_config/manager",
+- std::array<const char*, 0>());
+- });
++ else
++ {
++ BMCWEB_LOG_ERROR
++ << "Unsupported attribute type.";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ }
++ },
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "PendingAttributes");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
++ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings")
+- .privileges({{"ConfigureComponents"}})
+- .methods(boost::beast::http::verb::patch)(
+- [](const crow::Request& req,
+- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+- nlohmann::json inpJson;
++ .privileges(redfish::privileges::patchBios)
++ .methods(
++ boost::beast::http::verb::
++ patch)([](const crow::Request& req,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ nlohmann::json inpJson;
+
+- if (!redfish::json_util::readJsonPatch(req, asyncResp->res, "data",
+- inpJson))
+- {
+- return;
+- }
++ if (!redfish::json_util::readJsonPatch(req, asyncResp->res, "data",
++ inpJson))
++ {
++ BMCWEB_LOG_ERROR << "No 'data' in req!";
++ return;
++ }
+
+- for (auto& attrInfo : inpJson)
+- {
+- std::optional<std::string> attrName;
+- std::optional<std::string> attrType;
+- std::optional<std::string> attrValue;
+- if (!json_util::getValueFromJsonObject(
+- attrInfo, "AttributeName", attrName))
+- {
+- messages::propertyMissing(asyncResp->res,
+- "AttributeName");
+- return;
+- }
+- if (!json_util::getValueFromJsonObject(
+- attrInfo, "AttributeType", attrType))
+- {
+- messages::propertyMissing(asyncResp->res,
+- "AttributeType");
+- return;
+- }
+- if (!json_util::getValueFromJsonObject(
+- attrInfo, "AttributeValue", attrValue))
++ if (inpJson.empty())
++ {
++ messages::invalidObject(asyncResp->res,
++ crow::utility::urlFromPieces("data"));
++ BMCWEB_LOG_ERROR << "No input in req!";
++ return;
++ }
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp, inpJson](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
+ {
+- messages::propertyMissing(asyncResp->res,
+- "AttributeValue");
++ BMCWEB_LOG_ERROR
++ << "ObjectMapper::GetObject call failed: " << ec;
++ messages::internalError(asyncResp->res);
++
+ return;
+ }
+- std::string biosAttrType = mapRedfishToAttrType(*attrType);
+
+- if (biosAttrType == "UNKNOWN")
++ if (getObjectType.empty())
+ {
+- BMCWEB_LOG_ERROR << "Invalid attribute type";
+- messages::propertyValueNotInList(
+- asyncResp->res, "AttributeType", *attrType);
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
+ return;
+ }
+
+- PendingAttributesType pendingAttributes;
+- pendingAttributes.emplace_back(std::make_pair(
+- *attrName, std::make_tuple(biosAttrType, *attrValue)));
++ std::string service = getObjectType.begin()->first;
+
+ crow::connections::systemBus->async_method_call(
+- [asyncResp](const boost::system::error_code ec) {
++ [asyncResp,
++ inpJson](const boost::system::error_code ec,
++ const std::variant<BiosBaseTableType>&
++ retBiosTable) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+- << "doPatch resp_handler got error " << ec;
++ << "getBiosAttributes DBUS error: " << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const BiosBaseTableType* baseBiosTable =
++ std::get_if<BiosBaseTableType>(&retBiosTable);
++
++ if (baseBiosTable == nullptr)
++ {
++ BMCWEB_LOG_ERROR << "baseBiosTable is empty.";
+ messages::internalError(asyncResp->res);
+ return;
+ }
++
++ PendingAttributesType pendingAttributes{};
++
++ for (nlohmann::detail::iteration_proxy_value<
++ nlohmann::detail::iter_impl<
++ const nlohmann::basic_json<>>>&
++ attributes : inpJson.items())
++ {
++ BiosBaseTableType::const_iterator knobIter =
++ baseBiosTable->find(attributes.key());
++ if (knobIter == baseBiosTable->end())
++ {
++ BMCWEB_LOG_ERROR << "Cannot find "
++ << attributes.key()
++ << " in baseBiosTable";
++ messages::propertyValueNotInList(
++ asyncResp->res, attributes.key(),
++ "data");
++ return;
++ }
++
++ const std::string& itemType =
++ std::get<biosBaseAttrType>(
++ knobIter->second);
++ std::string attrType =
++ mapAttrTypeToRedfish(itemType);
++
++ if (attrType == "String" ||
++ attrType == "Enumeration")
++ {
++ std::string val = attributes.value();
++
++ pendingAttributes.emplace(
++ attributes.key(),
++ std::make_tuple(itemType, val));
++ }
++ else if (attrType == "Integer")
++ {
++ pendingAttributes.emplace(
++ attributes.key(),
++ std::make_tuple(
++ itemType, static_cast<int64_t>(
++ attributes.value())));
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "UNKNOWN attrType == "
++ << itemType;
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++ }
++
++ if (pendingAttributes.empty())
++ {
++ BMCWEB_LOG_ERROR
++ << "pendingAttributes is empty.";
++ messages::invalidObject(
++ asyncResp->res,
++ crow::utility::urlFromPieces("data"));
++ }
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](
++ const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "doPatch resp_handler got error "
++ << ec << "\n";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ messages::success(asyncResp->res);
++ },
++ "xyz.openbmc_project.BIOSConfigManager",
++ "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Set",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "PendingAttributes",
++ std::variant<PendingAttributesType>(
++ pendingAttributes));
+ },
+- "xyz.openbmc_project.BIOSConfigManager",
+- "/xyz/openbmc_project/bios_config/manager",
+- "org.freedesktop.DBus.Properties", "Set",
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.BIOSConfig.Manager",
+- "PendingAttributes",
+- std::variant<PendingAttributesType>(pendingAttributes));
+- }
+- });
++ "BaseBIOSTable");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
++ });
+ }
+ /**
+ * BiosAttributeRegistry class supports handle get method for BIOS attribute
+@@ -555,6 +654,15 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+
+ return;
+ }
++
++ if (getObjectType.empty())
++ {
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++
+ std::string service = getObjectType.begin()->first;
+
+ crow::connections::systemBus->async_method_call(
+@@ -575,8 +683,6 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ nlohmann::json& attributeArray =
+ asyncResp->res
+ .jsonValue["RegistryEntries"]["Attributes"];
+- nlohmann::json optionsArray =
+- nlohmann::json::array();
+ if (baseBiosTable == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
+@@ -592,10 +698,11 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ mapAttrTypeToRedfish(itemType);
+ if (attrType == "UNKNOWN")
+ {
+- BMCWEB_LOG_ERROR << "attrType == UNKNOWN";
+- messages::internalError(asyncResp->res);
+- return;
++ BMCWEB_LOG_ERROR << "UNKNOWN attrType == "
++ << itemType;
++ continue;
+ }
++
+ nlohmann::json attributeItem;
+ attributeItem["AttributeName"] = item.first;
+ attributeItem["Type"] = attrType;
+@@ -609,16 +716,37 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ attributeItem["MenuPath"] =
+ std::get<biosBaseMenuPath>(item.second);
+
+- if (attrType == "String")
++ if (attrType == "String" ||
++ attrType == "Enumeration")
+ {
+ const std::string* currValue =
+ std::get_if<std::string>(
+ &std::get<biosBaseCurrValue>(
+ item.second));
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, no "
++ "std::string data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ const std::string* defValue =
+ std::get_if<std::string>(
+ &std::get<biosBaseDefaultValue>(
+ item.second));
++
++ if (!defValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get defValue, no "
++ "std::string data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ attributeItem["CurrentValue"] =
+ currValue != nullptr ? *currValue : "";
+ attributeItem["DefaultValue"] =
+@@ -630,10 +758,30 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<int64_t>(
+ &std::get<biosBaseCurrValue>(
+ item.second));
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, no "
++ "int64_t data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ const int64_t* defValue =
+ std::get_if<int64_t>(
+ &std::get<biosBaseDefaultValue>(
+ item.second));
++
++ if (!defValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get defValue, no "
++ "int64_t data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ attributeItem["CurrentValue"] =
+ currValue != nullptr ? *currValue : 0;
+ attributeItem["DefaultValue"] =
+@@ -641,12 +789,13 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ }
+ else
+ {
+- BMCWEB_LOG_ERROR
+- << "Unsupported attribute type.";
+- messages::internalError(asyncResp->res);
+- return;
++ BMCWEB_LOG_ERROR << "UNKNOWN attrType == "
++ << itemType;
++ continue;
+ }
+
++ nlohmann::json optionsArray =
++ nlohmann::json::array();
+ const std::vector<OptionsItemType>&
+ optionsVector =
+ std::get<biosBaseOptions>(item.second);
+@@ -661,9 +810,9 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ if (optItemTypeRedfish == "UNKNOWN")
+ {
+ BMCWEB_LOG_ERROR
+- << "optItemTypeRedfish == UNKNOWN";
+- messages::internalError(asyncResp->res);
+- return;
++ << "UNKNOWN optItemTypeRedfish == "
++ << strOptItemType;
++ continue;
+ }
+ if (optItemTypeRedfish == "OneOf")
+ {
+@@ -671,7 +820,21 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<std::string>(
+ &std::get<optItemValue>(
+ optItem));
+- optItemJson[optItemTypeRedfish] =
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, "
++ "no "
++ "std::string data in option "
++ "item value";
++ continue;
++ }
++
++ optItemJson["ValueDisplayName"] =
++ currValue != nullptr ? *currValue
++ : "";
++ optItemJson["ValueName"] =
+ currValue != nullptr ? *currValue
+ : "";
+ }
+@@ -681,7 +844,21 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<int64_t>(
+ &std::get<optItemValue>(
+ optItem));
+- optItemJson[optItemTypeRedfish] =
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, "
++ "no "
++ "int64_t data in option "
++ "item value";
++ continue;
++ }
++
++ optItemJson["ValueDisplayName"] =
++ currValue != nullptr ? *currValue
++ : 0;
++ optItemJson["ValueName"] =
+ currValue != nullptr ? *currValue
+ : 0;
+ }
+@@ -689,6 +866,12 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ optionsArray.push_back(optItemJson);
+ }
+
++ if (optionsArray.empty())
++ {
++ BMCWEB_LOG_ERROR << "optionsArray is empty";
++ continue;
++ }
++
+ attributeItem["Value"] = optionsArray;
+ attributeArray.push_back(attributeItem);
+ }
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch
new file mode 100644
index 000000000..dbd5700be
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch
@@ -0,0 +1,76 @@
+From dd8160fefbac27d7f2ec99bf8b54c599083bcdbd Mon Sep 17 00:00:00 2001
+From: Snehalatha Venkatesh <snehalathax.v@intel.com>
+Date: Tue, 28 Dec 2021 11:05:50 +0000
+Subject: [PATCH] Add BiosAttributeRegistry node under Registries.
+
+/redfish/v1/Registries/ is missing node BiosAttributeRegistry
+under it. Added code to fix the same.
+
+Tested:
+1.Ran Redfish Validator and passed.
+2.GET - /redfish/v1/Registries/
+
+Response:
+{
+"@odata.id": "/redfish/v1/Registries",
+"@odata.type": "#MessageRegistryFileCollection.MessageRegistryFileCollection",
+"Description": "Collection of MessageRegistryFiles",
+"Members": [
+{
+"@odata.id": "/redfish/v1/Registries/Base"
+},
+{
+"@odata.id": "/redfish/v1/Registries/TaskEvent"
+},
+{
+"@odata.id": "/redfish/v1/Registries/ResourceEvent"
+},
+{
+"@odata.id": "/redfish/v1/Registries/BiosAttributeRegistry"
+},
+{
+"@odata.id": "/redfish/v1/Registries/OpenBMC"
+}
+],
+"Members@odata.count": 5,
+"Name": "MessageRegistryFile Collection"
+}
+
+Signed-off-by: Snehalatha Venkatesh <snehalathax.v@intel.com>
+---
+ redfish-core/lib/message_registries.hpp | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp
+index d76f70b..4ae8383 100644
+--- a/redfish-core/lib/message_registries.hpp
++++ b/redfish-core/lib/message_registries.hpp
+@@ -41,11 +41,12 @@ inline void handleMessageRegistryFileCollectionGet(
+ {"@odata.id", "/redfish/v1/Registries"},
+ {"Name", "MessageRegistryFile Collection"},
+ {"Description", "Collection of MessageRegistryFiles"},
+- {"Members@odata.count", 4},
++ {"Members@odata.count", 5},
+ {"Members",
+ {{{"@odata.id", "/redfish/v1/Registries/Base"}},
+ {{"@odata.id", "/redfish/v1/Registries/TaskEvent"}},
+ {{"@odata.id", "/redfish/v1/Registries/ResourceEvent"}},
++ {{"@odata.id", "/redfish/v1/Registries/BiosAttributeRegistry"}},
+ {{"@odata.id", "/redfish/v1/Registries/OpenBMC"}}}}};
+ }
+
+@@ -89,6 +90,11 @@ inline void handleMessageRoutesMessageRegistryFileGet(
+ header = &registries::resource_event::header;
+ url = registries::resource_event::url;
+ }
++ else if (registry == "BiosAttributeRegistry")
++ {
++ header = &registries::bios::header;
++ dmtf.clear();
++ }
+ else
+ {
+ messages::resourceNotFound(
+--
+2.25.1
+