Initial patch for RBC BIOS Config Manager
ResetBIOSSettings is not implemented as part of this patch apart from
that GetAttribute, SetAttribute and setters for BaseBIOSTable,
PendingAttributes is implemeted.
Interface:
xyz.openbmc_project.BIOSConfig.Manager
Properties:
.BaseBIOSTable property a{s(sbsssvva(sv))} 1 "testAttributeName" "xyz.openbmc_pr... emits-change writable
.PendingAttributes property a{s(sv)} 2 "test1" "xyz.openbmc_project.BIOSCo... emits-change writable
.ResetBIOSSettings property s "xyz.openbmc_project.BIOSConfig.Manag... emits-change writable
Methods:
.GetAttribute method s svv -
.SetAttribute method sv - -
Tested:
1. Service is working well.
2. All the dbus methods and properties are shown correctly.
3. Unit test done.
a). Tree
root@intel-obmc:~# busctl tree xyz.openbmc_project.BIOSConfigManager
`-/xyz
`-/xyz/openbmc_project
`-/xyz/openbmc_project/bios_config
`-/xyz/openbmc_project/bios_config/manager
b). Instrospect
root@intel-obmc:~# busctl introspect xyz.openbmc_project.BIOSConfigManager /xyz/openbmc_project/bios_config/manager
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
xyz.openbmc_project.BIOSConfig.Manager interface - - -
.GetAttribute method s svv -
.SetAttribute method sv - -
.BaseBIOSTable property a{s(sbsssvva(sv))} 2 "attr0" "xyz.openbmc_project.BIOSCo... emits-change writable
.PendingAttributes property a{s(sv)} 1 "test1" "xyz.openbmc_project.BIOSCo... emits-change writable
.ResetBIOSSettings property s "xyz.openbmc_project.BIOSConfig.Manag... emits-change writable
c). Method: GetAttribute/SetAttribute
root@intel-obmc:~# busctl call xyz.openbmc_project.BIOSConfigManager /xyz/openbmc_project/bios_config/manager xyz.openbmc_project.BIOSConfig.Manager SetAttribute sv test1 s "value"
root@intel-obmc:~# busctl call xyz.openbmc_project.BIOSConfigManager /xyz/openbmc_project/bios_config/manager xyz.openbmc_project.BIOSConfig.Manager GetAttribute s test1
svv "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String" x 0 s "value"
d). Service
root@intel-obmc:~# systemctl status xyz.openbmc_project.biosconfig_manager
* xyz.openbmc_project.biosconfig_manager.service - BIOS Config Manager - For Remote BIOS configuration update
Loaded: loaded (8;;file://intel-obmc/lib/systemd/system/xyz.openbmc_project.biosconfig_manager.service/lib/systemd/system/xyz.openbmc_project.biosconfig_manager.service8;;; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/xyz.openbmc_project.biosconfig_manager.service.d
`-8;;file://intel-obmc/etc/systemd/system/xyz.openbmc_project.biosconfig_manager.service.d/watchdog.confwatchdog.conf8;;
Active: active (running) since Thu 1970-01-01 00:00:56 UTC; 25min ago
Main PID: 394 (biosconfig-mana)
CGroup: /system.slice/xyz.openbmc_project.biosconfig_manager.service
`-394 /usr/bin/biosconfig-manager
Jan 01 00:00:56 intel-obmc systemd[1]: Started BIOS Config Manager - For Remote BIOS configuration update.
Change-Id: I7a7312ffbdf000aab254c77ed5e4f9a8d4ec4d45
Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
diff --git a/src/manager.cpp b/src/manager.cpp
new file mode 100644
index 0000000..c4c660d
--- /dev/null
+++ b/src/manager.cpp
@@ -0,0 +1,281 @@
+/*
+// 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.
+*/
+#include "manager.hpp"
+
+#include "xyz/openbmc_project/BIOSConfig/Common/error.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <boost/asio.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+namespace bios_config
+{
+
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+using namespace sdbusplus::xyz::openbmc_project::BIOSConfig::Common::Error;
+
+void Manager::setAttribute(AttributeName attribute, AttributeValue value)
+{
+ auto pendingAttrs = Base::pendingAttributes();
+ auto iter = pendingAttrs.find(attribute);
+
+ if (iter != pendingAttrs.end())
+ {
+ std::get<1>(iter->second) = value;
+ }
+ else
+ {
+ Manager::PendingAttribute attributeValue;
+
+ if (std::get_if<int64_t>(&value))
+ {
+ std::get<0>(attributeValue) = AttributeType::Integer;
+ }
+ else
+ {
+ std::get<0>(attributeValue) = AttributeType::String;
+ }
+
+ std::get<1>(attributeValue) = value;
+ pendingAttrs.emplace(attribute, attributeValue);
+ }
+
+ pendingAttributes(pendingAttrs);
+}
+
+Manager::AttributeDetails Manager::getAttribute(AttributeName attribute)
+{
+ Manager::AttributeDetails value;
+
+ auto table = Base::baseBIOSTable();
+ auto iter = table.find(attribute);
+
+ if (iter != table.end())
+ {
+ std::get<0>(value) =
+ std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
+ std::get<1>(value) =
+ std::get<static_cast<uint8_t>(Index::currentValue)>(iter->second);
+
+ auto pending = Base::pendingAttributes();
+ auto pendingIter = pending.find(attribute);
+ if (pendingIter != pending.end())
+ {
+ std::get<2>(value) = std::get<1>(pendingIter->second);
+ }
+ else if (std::get_if<std::string>(&std::get<1>(value)))
+ {
+ std::get<2>(value) = std::string();
+ }
+ }
+ else
+ {
+ throw AttributeNotFound();
+ }
+
+ return value;
+}
+
+Manager::BaseTable Manager::baseBIOSTable(BaseTable value)
+{
+ pendingAttributes({});
+ return Base::baseBIOSTable(value, false);
+}
+
+Manager::PendingAttributes Manager::pendingAttributes(PendingAttributes value)
+{
+ // Clear the pending attributes
+ if (value.empty())
+ {
+ return Base::pendingAttributes({}, false);
+ }
+
+ // Validate all the BIOS attributes before setting PendingAttributes
+ BaseTable biosTable = Base::baseBIOSTable();
+ for (const auto& pair : value)
+ {
+ auto iter = biosTable.find(pair.first);
+ // BIOS attribute not found in the BaseBIOSTable
+ if (iter == biosTable.end())
+ {
+ throw AttributeNotFound();
+ }
+
+ // BIOS attribute is read only
+ if (std::get<static_cast<uint8_t>(Index::readOnly)>(iter->second))
+ {
+ throw AttributeReadOnly();
+ }
+
+ auto attributeType =
+ std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
+ if (attributeType != std::get<0>(pair.second))
+ {
+ throw InvalidArgument();
+ }
+
+ // Validate enumeration BIOS attributes
+ if (attributeType == AttributeType::Enumeration)
+ {
+ // For enumeration the expected variant types is std::string
+ if (std::get<1>(pair.second).index() == 0)
+ {
+ throw InvalidArgument();
+ }
+
+ const auto& attrValue =
+ std::get<std::string>(std::get<1>(pair.second));
+ const auto& options =
+ std::get<static_cast<uint8_t>(Index::options)>(iter->second);
+
+ bool found = false;
+ for (const auto& enumOptions : options)
+ {
+ if ((BoundType::OneOf == std::get<0>(enumOptions)) &&
+ (attrValue ==
+ std::get<std::string>(std::get<1>(enumOptions))))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ throw InvalidArgument();
+ }
+ }
+
+ if (attributeType == AttributeType::String)
+ {
+ // For enumeration the expected variant types is std::string
+ if (std::get<1>(pair.second).index() == 0)
+ {
+ throw InvalidArgument();
+ }
+
+ const auto& attrValue =
+ std::get<std::string>(std::get<1>(pair.second));
+ const auto& options =
+ std::get<static_cast<uint8_t>(Index::options)>(iter->second);
+ int64_t minStringLength = 0;
+ int64_t maxStringLength = 0;
+
+ for (const auto& stringOptions : options)
+ {
+ if (BoundType::MinStringLength == std::get<0>(stringOptions))
+ {
+ minStringLength =
+ std::get<int64_t>(std::get<1>(stringOptions));
+ }
+ else if (BoundType::MaxStringLength ==
+ std::get<0>(stringOptions))
+ {
+ maxStringLength =
+ std::get<int64_t>(std::get<1>(stringOptions));
+ }
+ }
+
+ if ((attrValue.length() < static_cast<size_t>(minStringLength)) ||
+ (attrValue.length() > static_cast<size_t>(maxStringLength)))
+ {
+ throw InvalidArgument();
+ }
+ }
+
+ if (attributeType == AttributeType::Integer)
+ {
+ // For enumeration the expected variant types is std::string
+ if (std::get<1>(pair.second).index() == 1)
+ {
+ throw InvalidArgument();
+ }
+
+ const auto& attrValue = std::get<int64_t>(std::get<1>(pair.second));
+ const auto& options =
+ std::get<static_cast<uint8_t>(Index::options)>(iter->second);
+ int64_t lowerBound = 0;
+ int64_t upperBound = 0;
+ int64_t scalarIncrement = 0;
+
+ for (const auto& integerOptions : options)
+ {
+ if (BoundType::LowerBound == std::get<0>(integerOptions))
+ {
+ lowerBound = std::get<int64_t>(std::get<1>(integerOptions));
+ }
+ else if (BoundType::UpperBound == std::get<0>(integerOptions))
+ {
+ upperBound = std::get<int64_t>(std::get<1>(integerOptions));
+ }
+ else if (BoundType::ScalarIncrement ==
+ std::get<0>(integerOptions))
+ {
+ scalarIncrement =
+ std::get<int64_t>(std::get<1>(integerOptions));
+ }
+ }
+
+ if ((attrValue < lowerBound) || (attrValue > upperBound))
+ {
+ throw InvalidArgument();
+ }
+
+ if (((std::abs(attrValue - lowerBound)) % scalarIncrement) != 0)
+ {
+ throw InvalidArgument();
+ }
+ }
+ }
+
+ PendingAttributes pendingAttribute = Base::pendingAttributes();
+
+ for (const auto& pair : value)
+ {
+ auto iter = pendingAttribute.find(pair.first);
+ if (iter != pendingAttribute.end())
+ {
+ iter = pendingAttribute.erase(iter);
+ }
+
+ pendingAttribute.emplace(std::make_pair(pair.first, pair.second));
+ }
+
+ return Base::pendingAttributes(pendingAttribute, false);
+}
+
+Manager::Manager(sdbusplus::asio::object_server& objectServer,
+ std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
+ sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager(*systemBus,
+ objectPath),
+ objServer(objectServer), systemBus(systemBus)
+{}
+
+} // namespace bios_config
+
+int main()
+{
+ boost::asio::io_service io;
+ auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+
+ systemBus->request_name(bios_config::service);
+ sdbusplus::asio::object_server objectServer(systemBus);
+ bios_config::Manager manager(objectServer, systemBus);
+
+ io.run();
+ return 0;
+}