Add depex support in bios.xml parsing.
Added logic to execute depex expression for every knob in bios.xml.
knob is added to BiosAttributeRegistry only if depex evaluation result
is TRUE.
Tested:
By giving GET Request to
'redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry'.
Output sample showing few knobs added becuase depex evaluation result
was TRUE:
{
"AttributeName": "AEPErrorInjEn",
"CurrentValue": "0x00",
"DefaultValue": "0x00",
"DisplayName": "AEPErrorInjEn",
"HelpText": "Enable/Disable PMem Error Injection",
"MenuPath": "./",
"ReadOnly": false,
"Type": "String",
"Value": [
{
"OneOf": "0x0"
},
{
"OneOf": "0x1"
}
]
}
{
"AttributeName": "wrVrefCenter",
"CurrentValue": "0x01",
"DefaultValue": "0x01",
"DisplayName": "wrVrefCenter",
"HelpText": "Write Vref Centering Disable/Enable",
"MenuPath": "./",
"ReadOnly": false,
"Type": "String",
"Value": [
{
"OneOf": "0x0"
},
{
"OneOf": "0x1"
}
]
}
Following are few knobs rejected becuase depex evaluation
result was FALSE:
<knob type="scalar" setupType="oneof" name="PfrProvision"
varstoreIndex="04" prompt="PFR Provision"
description="Selectable if PFR is not locked." size="1"
offset="0x0126"
depex="Sif( PfrSupported _EQU_ 0 ) _AND_ Gif( PfrLockStatus _EQU_ 1 OR
PfrProvisionStatus _EQU_ 1 )"
default="0x00" CurrentVal="0x00">
<options>
<option text="Disable" value="0x0"/>
<option text="Enable" value="0x1"/>
</options>
</knob>
<knob type="scalar" setupType="oneof" name="SataHotPlugController0_0"
varstoreIndex="01" prompt="
Hot Plug" description="Designates this port as Hot Pluggable." size="1"
offset="0x0119"
depex="Sif( PchSata_0 _EQU_ 0 ) _AND_
Sif( SataExternalController0_0 _EQU_ 1 )" default="0x00"
CurrentVal="0x00">
<options>
<option text="Disabled" value="0x0"/>
<option text="Enabled" value="0x1"/>
</options>
</knob>
Signed-off-by: Arun Lal K M <arun.lal@intel.com>
Change-Id: Iff1ea01fb06200e21cc7f2a2e0fdfdff70376581
diff --git a/src/biosconfigcommands.cpp b/src/biosconfigcommands.cpp
index 6734745..6d48f8f 100644
--- a/src/biosconfigcommands.cpp
+++ b/src/biosconfigcommands.cpp
@@ -14,8 +14,9 @@
// limitations under the License.
*/
+#include "biosxml.hpp"
+
#include <openssl/sha.h>
-#include <tinyxml2.h>
#include <biosconfigcommands.hpp>
#include <boost/crc.hpp>
@@ -28,8 +29,6 @@
#include <ipmid/utils.hpp>
#include <nlohmann/json.hpp>
#include <oemcommands.hpp>
-#include <phosphor-logging/elog-errors.hpp>
-#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/message/types.hpp>
@@ -72,16 +71,8 @@
description,menuPath,current,default,
array{struct{optionstring,optionvalue}}}}
*/
-using BiosBaseTableType =
- std::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>>>>>;
-using OptionType =
- std::vector<std::tuple<std::string, std::variant<int64_t, std::string>>>;
-BiosBaseTableType attributesData;
+
+bios::BiosBaseTableType attributesData;
NVOOBdata gNVOOBdata;
@@ -118,24 +109,44 @@
/** @brief implement to set the BaseBIOSTable property
* @returns status
*/
-static int sendAllAttributes(ipmi::Context::ptr ctx)
+static bool sendAllAttributes(std::string service)
{
- boost::system::error_code ec;
- std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
- std::string service =
- getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
- ec.clear();
- ctx->bus->yield_method_call<>(
- ctx->yield, ec, service, biosConfigBaseMgrPath,
- "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
- "BaseBIOSTable", std::variant<BiosBaseTableType>(attributesData));
- if (ec)
+ std::shared_ptr<sdbusplus::asio::connection> pSdBusPlus = getSdBus();
+
+ if (pSdBusPlus)
{
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "Failed to sendAllAttributes");
- return -1;
+ try
+ {
+ pSdBusPlus->async_method_call(
+ [](const boost::system::error_code ec) {
+ /* No more need to keep attributes data in memory */
+ attributesData.clear();
+
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "sendAllAttributes error: send all attributes - "
+ "failed");
+ return;
+ }
+
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "sendAllAttributes: send all attributes - done");
+ },
+ service, biosConfigBaseMgrPath,
+ "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
+ "BaseBIOSTable",
+ std::variant<bios::BiosBaseTableType>(attributesData));
+
+ return true;
+ }
+ catch (std::exception& ex)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
+ }
}
- return 0;
+
+ return false;
}
/** @brief implement to flush the updated data in nv space
@@ -221,95 +232,66 @@
}
}
-/** @brief implement generate naive- dbus from XML file
- * @returns status
+/** @brief Get attributes data (bios base table) from bios.xml
*/
-static int generateAttributesData()
+static bool generateAttributesData()
{
- // Open the bios.xml and parse it
- // Extract the needed data and store it in AttributesData variable
- // Close the bios.xml
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "generateAttributesData");
- tinyxml2::XMLDocument xmlDoc;
+ try
+ {
+ bios::Xml biosxml(biosXMLFilePath);
- xmlDoc.LoadFile(biosXMLFilePath);
- tinyxml2::XMLNode* pRoot = xmlDoc.FirstChild();
- if (pRoot == nullptr)
- {
- return ipmi::ccUnspecifiedError;
- }
- tinyxml2::XMLElement* pElement = pRoot->FirstChildElement("biosknobs");
- if (pElement == nullptr)
- {
- return ipmi::ccUnspecifiedError;
- }
- tinyxml2::XMLElement* pKnobsElement = pElement->FirstChildElement("knob");
-
- while (pKnobsElement != nullptr)
- {
- bool readOnlyStatus = false;
- std::string attrType =
- "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String";
- std::string name, curvalue, dname, menupath, defaultvalue, description;
- name = pKnobsElement->Attribute("name")
- ? pKnobsElement->Attribute("name")
- : "";
- curvalue = pKnobsElement->Attribute("CurrentVal")
- ? pKnobsElement->Attribute("CurrentVal")
- : "";
- dname = pKnobsElement->Attribute("prompt")
- ? pKnobsElement->Attribute("prompt")
- : "";
- menupath = pKnobsElement->Attribute("SetupPgPtr")
- ? pKnobsElement->Attribute("SetupPgPtr")
- : "";
- defaultvalue = pKnobsElement->Attribute("default")
- ? pKnobsElement->Attribute("default")
- : "";
- description = pKnobsElement->Attribute("description")
- ? pKnobsElement->Attribute("description")
- : "";
- if (!name.empty() && !curvalue.empty() && !dname.empty() &&
- !menupath.empty() && !defaultvalue.empty())
+ if (!biosxml.doDepexCompute())
{
- std::string rootPath = "./" + std::string(menupath);
-
- OptionType optionArray;
- tinyxml2::XMLElement* pOptionsElement =
- pKnobsElement->FirstChildElement("options");
- nlohmann::json optionsArray = nlohmann::json::array();
- if (pOptionsElement != nullptr)
- {
- tinyxml2::XMLElement* pOptionElement =
- pOptionsElement->FirstChildElement("option");
- while (pOptionElement != nullptr)
- {
- const std::string optType =
- "xyz.openbmc_project.BIOSConfig.Manager.BoundType."
- "OneOf";
- const std::string attrValue =
- pOptionElement->Attribute("value");
- if (!optType.empty() && !attrValue.empty())
- {
-
- optionArray.push_back(
- std::make_pair(optType, attrValue));
- }
- pOptionElement =
- pOptionElement->NextSiblingElement("option");
- }
- }
-
- attributesData.emplace(std::make_pair(
- name, std::make_tuple(attrType, readOnlyStatus, dname,
- description, rootPath, curvalue,
- defaultvalue, optionArray)));
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "'depex' compute failed");
}
- pKnobsElement = pKnobsElement->NextSiblingElement("knob");
+
+ if (!biosxml.getBaseTable(attributesData))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Failed to get bios base table");
+ }
+ }
+ catch (std::exception& ex)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
+ return false;
}
- return ipmi::ccSuccess;
+ return true;
+}
+
+/** @brief Generate attributes data from bios.xml
+ * and send attributes data (bios base table) to dbus using set method.
+ */
+static void generateAndSendAttributesData(std::string service,
+ uint8_t payloadType)
+{
+ if (!generateAttributesData())
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "generateAndSendAttributesData: generateAttributesData - failed");
+ gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+ static_cast<uint8_t>(ipmi::PStatus::Corrupted);
+ return;
+ }
+
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "generateAndSendAttributesData : generateAttributesData is done");
+
+ if (!sendAllAttributes(service))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "generateAndSendAttributesData: sendAllAttributes - failed");
+ gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+ static_cast<uint8_t>(ipmi::PStatus::Corrupted);
+ return;
+ }
+
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "generateAndSendAttributesData : sendAllAttributes is done");
+ gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+ static_cast<uint8_t>(ipmi::PStatus::Valid);
}
/** @brief implement executing the linux command to uncompress and generate the
@@ -599,30 +581,26 @@
}
phosphor::logging::log<phosphor::logging::level::INFO>(
" ipmiOEMSetPayload : Convert XML into native-dbus DONE");
- response = generateAttributesData();
- if (response)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ipmiOEMSetPayload: generateAttributesData - failed");
- gNVOOBdata.payloadInfo[payloadType].payloadStatus =
- static_cast<uint8_t>(ipmi::PStatus::Corrupted);
- return ipmi::responseResponseError();
- }
- phosphor::logging::log<phosphor::logging::level::INFO>(
- " ipmiOEMSetPayload : BaseBIOSTable Property is set");
- response = sendAllAttributes(ctx);
- if (response)
+ /* So that we don't block the call */
+ auto io = getIoContext();
+ auto dbus = getSdBus();
+ if (io && dbus)
{
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ipmiOEMSetPayload: sendAllAttributes - failed");
- gNVOOBdata.payloadInfo[payloadType].payloadStatus =
- static_cast<uint8_t>(ipmi::PStatus::Corrupted);
+ std::string service = getService(*dbus, biosConfigIntf,
+ biosConfigBaseMgrPath);
+
+ boost::asio::post(*io, [service, payloadType] {
+ generateAndSendAttributesData(service, payloadType);
+ });
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "ipmiOEMSetPayload: Unable to get io context or sdbus");
return ipmi::responseResponseError();
}
}
- gNVOOBdata.payloadInfo[payloadType].payloadStatus =
- static_cast<uint8_t>(ipmi::PStatus::Valid);
struct stat filestat;