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/.clang-format b/.clang-format
new file mode 100644
index 0000000..52ac0a1
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,115 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterCaseLabel: true
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ AfterExternBlock: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+BreakInheritanceList: AfterColon
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 7
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.h"'
+ Priority: 1
+ - Regex: '^".*\.hpp"'
+ Priority: 2
+ - Regex: '^<.*\.h>'
+ Priority: 3
+ - Regex: '^<.*\.hpp>'
+ Priority: 4
+ - Regex: '^<.*'
+ Priority: 5
+ - Regex: '.*'
+ Priority: 6
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Latest
+TabWidth: 4
+UseTab: Never
+...
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b95a3ac
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+# meson
+
+/build
+/builddir
diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..20af752
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 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.
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100755
index 0000000..48467bb
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,46 @@
+How to use this list:
+ Find the most specific section entry (described below) that matches where
+ your change lives and add the reviewers (R) and maintainers (M) as
+ reviewers. You can use the same method to track down who knows a particular
+ code base best.
+
+ Your change/query may span multiple entries; that is okay.
+
+ If you do not find an entry that describes your request at all, someone
+ forgot to update this list; please at least file an issue or send an email
+ to a maintainer, but preferably you should just update this document.
+
+Description of section entries:
+
+ Section entries are structured according to the following scheme:
+
+ X: NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>
+ X: ...
+ .
+ .
+ .
+
+ Where REPO_NAME is the name of the repository within the OpenBMC GitHub
+ organization; FILE_PATH is a file path within the repository, possibly with
+ wildcards; X is a tag of one of the following types:
+
+ M: Denotes maintainer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
+ if omitted from an entry, assume one of the maintainers from the
+ MAINTAINERS entry.
+ R: Denotes reviewer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
+ these people are to be added as reviewers for a change matching the repo
+ path.
+ F: Denotes forked from an external repository; has fields URL.
+
+ Line comments are to be denoted "# SOME COMMENT" (typical shell style
+ comment); it is important to follow the correct syntax and semantics as we
+ may want to use automated tools with this file in the future.
+
+ A change cannot be added to an OpenBMC repository without a MAINTAINER's
+ approval; thus, a MAINTAINER should always be listed as a reviewer.
+
+START OF MAINTAINERS LIST
+-------------------------
+
+M: Suryakanth Sekar <suryakanth.sekar@linux.intel.com> <ssekar!>
+M: Kuiying Wang <kuiying.wang@intel.com> <kuiyingw!>
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..ce38e82
--- /dev/null
+++ b/README.md
@@ -0,0 +1,79 @@
+Remote BIOS Configuration via BMC
+Overview
+Provides ability for the user to view and modify the
+BIOS setup configuration parameters remotely via BMC at any Host state.
+Modifications to the parameters take place upon the next system reboot or
+immediate based on the host firmware.
+Please refer https://github.com/openbmc/docs/blob/master/designs/remoteBIOSConfiguration.md
+
+Remote BIOS Configuration (RBC) service exposes D-Bus methods for
+BIOS settings management operations.
+
+RBC Manager Interface
+xyz.openbmc_project.BIOSConfig.Manager provides following methods, properties.
+
+Object Path : /xyz/openbmc_project/BIOSConfig/Manager
+
+xyz.openbmc_project.BIOSConfig.Manager
+
+methods:
+SetAttribute -To set the particular BIOS attribute with new value.
+GetAttribute -To get the bios attribute current values and pending values if again.
+
+Properites:
+ResetBIOSSettings - Contain reset BIOS setting type:
+ Interface have to set NoAction this property,
+ when Reset BIOS settings are informed to the BIOS.
+BaseBIOSTable - Save the whole BIOS table.
+ map{attributeName,struct{attributeType,readonlyStatus,displayname,
+ description,menuPath,current,default,
+ array{struct{optionstring,optionvalue}}}}
+ Example 1:
+ {"DdrFreqLimit",
+ {xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String,
+ false,
+ "Memory Operating Speed Selection",
+ "Force specific Memory Operating Speed or use Auto setting.",
+ "Advanced/Memory Configuration/Memory Operating Speed Selection",
+ "0x00",
+ "0x0B",
+ { {"OneOf", "auto"},
+ {"OneOf", "2133"},
+ {"OneOf", "2400"},
+ {"OneOf", "2664"},
+ {"OneOf", "2933"}
+ }
+ }
+ }
+ Example 2:
+ {"BIOSSerialDebugLevel",
+ {xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer,
+ false,
+ "BIOS Serial Debug level",
+ "BIOS Serial Debug level during system boot.",
+ "Advanced/Debug Feature Selection",
+ 0x00,
+ 0x01,
+ { {"MinBound", 0},
+ {"MaxBound", 4},
+ {"ScalarIncrement",1}
+ }
+ }
+ }
+
+Signals:
+AttributeChanged - Signal sent out when attribute is changed
+
+PasswordInterface:
+
+xyz.openbmc_project.BIOSConfig.Password provides following Methods and Properities.
+
+xyz.openbmc_project.BIOSConfig.Password Interface
+
+Methods:
+ChangePassword - Change the BIOS setup password.
+
+Properities:
+PasswordInitialized - To indicate BIOS password related details are recevied or not.
+
+
diff --git a/include/manager.hpp b/include/manager.hpp
new file mode 100644
index 0000000..702e30f
--- /dev/null
+++ b/include/manager.hpp
@@ -0,0 +1,136 @@
+/*
+// 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 <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/BIOSConfig/Manager/server.hpp>
+
+#include <string>
+
+namespace bios_config
+{
+
+static constexpr auto service = "xyz.openbmc_project.BIOSConfigManager";
+static constexpr auto objectPath = "/xyz/openbmc_project/bios_config/manager";
+
+using Base = sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager;
+
+/** @class Manager
+ *
+ * @brief Implements the BIOS Manager
+ */
+class Manager : public Base
+{
+ public:
+ using BaseTable = std::map<
+ std::string,
+ std::tuple<AttributeType, bool, std::string, std::string, std::string,
+ std::variant<int64_t, std::string>,
+ std::variant<int64_t, std::string>,
+ std::vector<std::tuple<
+ BoundType, std::variant<int64_t, std::string>>>>>;
+
+ using PendingAttributes =
+ std::map<std::string,
+ std::tuple<AttributeType, std::variant<int64_t, std::string>>>;
+
+ using PendingAttribute =
+ std::tuple<AttributeType, std::variant<int64_t, std::string>>;
+
+ using AttributeName = std::string;
+ using AttributeValue = std::variant<int64_t, std::string>;
+ using CurrentValue = std::variant<int64_t, std::string>;
+ using PendingValue = std::variant<int64_t, std::string>;
+ using AttributeDetails =
+ std::tuple<AttributeType, CurrentValue, PendingValue>;
+
+ Manager() = delete;
+ ~Manager() = default;
+ Manager(const Manager&) = delete;
+ Manager& operator=(const Manager&) = delete;
+ Manager(Manager&&) = delete;
+ Manager& operator=(Manager&&) = delete;
+
+ /** @brief Constructs Manager object.
+ *
+ * @param[in] objectServer - object server
+ * @param[in] systemBus - bus connection
+ */
+ Manager(sdbusplus::asio::object_server& objectServer,
+ std::shared_ptr<sdbusplus::asio::connection>& systemBus);
+
+ /** @brief Set the BIOS attribute with a new value, the new value is added
+ * to the PendingAttribute.
+ *
+ * @param[in] attribute - attribute name
+ * @param[in] value - new value for the attribute
+ *
+ * @return On error, throw exception
+ */
+ void setAttribute(AttributeName attribute, AttributeValue value) override;
+
+ /** @brief Get the details of the BIOS attribute
+ *
+ * @param[in] attribute - attribute name
+ *
+ * @return On success, return the attribute details: attribute type,
+ * current value, pending value. On error, throw exception
+ */
+ AttributeDetails getAttribute(AttributeName attribute) override;
+
+ /** @brief Set the BaseBIOSTable property and clears the PendingAttributes
+ * property
+ *
+ * @param[in] value - new BaseBIOSTable
+ *
+ * @return The new BaseBIOSTable that is applied.
+ */
+ BaseTable baseBIOSTable(BaseTable value) override;
+
+ /** @brief Set the PendingAttributes property, additionally checks if the
+ * attributes are in the BaseBIOSTable, whether the attributes are
+ * read only and validate the attribute value based on the
+ * attribute type. PendingAttributes is cleared if value is empty.
+ *
+ * @param[in] value - new PendingAttributes to append to the
+ * PendingAttributes property
+ *
+ * @return On success, return the new PendingAttributes property that is
+ * set.Throw exception if the validation fails.
+ */
+ PendingAttributes pendingAttributes(PendingAttributes value) override;
+
+ private:
+ /** @enum Index into the fields in the BaseBIOSTable
+ */
+ enum class Index : uint8_t
+ {
+ attributeType = 0,
+ readOnly,
+ displayName,
+ description,
+ menuPath,
+ currentValue,
+ defaultValue,
+ options,
+ };
+
+ sdbusplus::asio::object_server& objServer;
+ std::shared_ptr<sdbusplus::asio::connection>& systemBus;
+};
+
+} // namespace bios_config
diff --git a/meson.build b/meson.build
new file mode 100755
index 0000000..e99c122
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,53 @@
+project(
+ 'biosconfig-manager',
+ 'cpp',
+ default_options: [
+ 'warning_level=3',
+ 'werror=true',
+ 'cpp_std=c++17'
+ ],
+ license: 'Apache-2.0',
+ version: '1.0',
+)
+
+# Wno-psabi reduces the number of "Note:" messages when cross-compiling some STL
+# stuff for ARM. See https://stackoverflow.com/questions/48149323/strange-gcc-warning-when-compiling-qt-project
+# Basically, gcc 6 and gcc 7 are not ABI compatible, but since the whole OpenBMC
+# project uses the same compiler, we can safely ignmore these info notes.
+add_project_arguments('-Wno-psabi', language: 'cpp')
+
+boost_args = ['-DBOOST_ALL_NO_LIB',
+ '-DBOOST_ASIO_DISABLE_THREADS',
+ '-DBOOST_ERROR_CODE_HEADER_ONLY',
+ '-DBOOST_NO_RTTI',
+ '-DBOOST_NO_TYPEID',
+ '-DBOOST_SYSTEM_NO_DEPRECATED']
+
+deps = [dependency('boost'),
+ dependency('phosphor-dbus-interfaces'),
+ dependency('phosphor-logging'),
+ dependency('sdbusplus'),
+ dependency('systemd'),
+]
+
+executable('biosconfig-manager',
+ 'src/manager.cpp',
+ implicit_include_directories: false,
+ include_directories: ['include'],
+ dependencies: deps,
+ cpp_args : boost_args,
+ install: true,
+ install_dir: get_option('bindir'))
+
+systemd = dependency('systemd')
+systemd_system_unit_dir = systemd.get_pkgconfig_variable(
+ 'systemdsystemunitdir',
+ define_variable: ['prefix', get_option('prefix')])
+
+configure_file(
+ copy: true,
+ input: 'service_files/xyz.openbmc_project.biosconfig_manager.service',
+ install: true,
+ install_dir: systemd_system_unit_dir,
+ output: 'xyz.openbmc_project.biosconfig_manager.service'
+)
diff --git a/service_files/xyz.openbmc_project.biosconfig_manager.service b/service_files/xyz.openbmc_project.biosconfig_manager.service
new file mode 100755
index 0000000..982f86b
--- /dev/null
+++ b/service_files/xyz.openbmc_project.biosconfig_manager.service
@@ -0,0 +1,12 @@
+[Unit]
+Description= BIOS Config Manager - For Remote BIOS configuration update
+
+[Service]
+Restart=always
+ExecStart=/usr/bin/biosconfig-manager
+SyslogIdentifier=biosconfig-manager
+Type=dbus
+BusName=xyz.openbmc_project.BIOSConfigManager
+
+[Install]
+WantedBy=multi-user.target
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;
+}