blob: 9581e15dbd3c63fb9aca298c675662d2c6aedd4e [file] [log] [blame]
Kuiying Wang642f4372020-08-12 15:35:46 +08001/*
Manojkiran Edafae57322024-11-12 12:58:11 +05302 Copyright (c) 2020 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http:www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
Kuiying Wang642f4372020-08-12 15:35:46 +080015*/
Manojkiran Edafae57322024-11-12 12:58:11 +053016
Kuiying Wang642f4372020-08-12 15:35:46 +080017#include "manager.hpp"
18
Tom Josephf1101df2020-11-06 08:23:34 +053019#include "manager_serialize.hpp"
Kuiying Wang642f4372020-08-12 15:35:46 +080020#include "xyz/openbmc_project/BIOSConfig/Common/error.hpp"
21#include "xyz/openbmc_project/Common/error.hpp"
22
23#include <boost/asio.hpp>
Kuiying Wang8f706212020-12-16 18:59:24 +080024#include <phosphor-logging/elog-errors.hpp>
George Liu567a3cf2021-12-08 10:36:03 +080025#include <phosphor-logging/lg2.hpp>
Kuiying Wang642f4372020-08-12 15:35:46 +080026#include <sdbusplus/asio/connection.hpp>
27#include <sdbusplus/asio/object_server.hpp>
28
29namespace bios_config
30{
31
32using namespace sdbusplus::xyz::openbmc_project::Common::Error;
33using namespace sdbusplus::xyz::openbmc_project::BIOSConfig::Common::Error;
34
35void Manager::setAttribute(AttributeName attribute, AttributeValue value)
36{
37 auto pendingAttrs = Base::pendingAttributes();
38 auto iter = pendingAttrs.find(attribute);
39
40 if (iter != pendingAttrs.end())
41 {
42 std::get<1>(iter->second) = value;
43 }
44 else
45 {
46 Manager::PendingAttribute attributeValue;
47
48 if (std::get_if<int64_t>(&value))
49 {
50 std::get<0>(attributeValue) = AttributeType::Integer;
51 }
52 else
53 {
54 std::get<0>(attributeValue) = AttributeType::String;
55 }
56
57 std::get<1>(attributeValue) = value;
58 pendingAttrs.emplace(attribute, attributeValue);
59 }
60
61 pendingAttributes(pendingAttrs);
62}
63
64Manager::AttributeDetails Manager::getAttribute(AttributeName attribute)
65{
66 Manager::AttributeDetails value;
67
68 auto table = Base::baseBIOSTable();
69 auto iter = table.find(attribute);
70
71 if (iter != table.end())
72 {
73 std::get<0>(value) =
74 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
75 std::get<1>(value) =
76 std::get<static_cast<uint8_t>(Index::currentValue)>(iter->second);
77
78 auto pending = Base::pendingAttributes();
79 auto pendingIter = pending.find(attribute);
80 if (pendingIter != pending.end())
81 {
82 std::get<2>(value) = std::get<1>(pendingIter->second);
83 }
84 else if (std::get_if<std::string>(&std::get<1>(value)))
85 {
86 std::get<2>(value) = std::string();
87 }
88 }
89 else
90 {
91 throw AttributeNotFound();
92 }
93
94 return value;
95}
96
97Manager::BaseTable Manager::baseBIOSTable(BaseTable value)
98{
99 pendingAttributes({});
Tom Josephf1101df2020-11-06 08:23:34 +0530100 auto baseTable = Base::baseBIOSTable(value, false);
101 serialize(*this, biosFile);
Snehalatha Venkatesh5e2cb722021-05-26 10:42:58 +0000102 Base::resetBIOSSettings(Base::ResetFlag::NoAction);
Tom Josephf1101df2020-11-06 08:23:34 +0530103 return baseTable;
Kuiying Wang642f4372020-08-12 15:35:46 +0800104}
105
yesad54c7c2022-12-29 22:38:32 +0530106bool Manager::validateEnumOption(
107 const std::string& attrValue,
Arun Lal K M1a448ad2023-05-03 12:35:28 +0000108 const std::vector<std::tuple<BoundType, std::variant<int64_t, std::string>,
109 std::string>>& options)
yesad54c7c2022-12-29 22:38:32 +0530110{
111 for (const auto& enumOptions : options)
112 {
113 if ((BoundType::OneOf == std::get<0>(enumOptions)) &&
114 (attrValue == std::get<std::string>(std::get<1>(enumOptions))))
115 {
116 return true;
117 }
118 }
119
120 lg2::error("No valid attribute");
121 return false;
122}
123
124bool Manager::validateStringOption(
125 const std::string& attrValue,
Arun Lal K M1a448ad2023-05-03 12:35:28 +0000126 const std::vector<std::tuple<BoundType, std::variant<int64_t, std::string>,
127 std::string>>& options)
yesad54c7c2022-12-29 22:38:32 +0530128{
129 size_t minStringLength = 0;
130 size_t maxStringLength = 0;
131 for (const auto& stringOptions : options)
132 {
133 if (BoundType::MinStringLength == std::get<0>(stringOptions))
134 {
135 minStringLength = std::get<int64_t>(std::get<1>(stringOptions));
136 }
137 else if (BoundType::MaxStringLength == std::get<0>(stringOptions))
138 {
139 maxStringLength = std::get<int64_t>(std::get<1>(stringOptions));
140 }
141 else
142 {
143 continue;
144 }
145 }
146
147 if (attrValue.length() < minStringLength ||
148 attrValue.length() > maxStringLength)
149 {
150 lg2::error(
151 "{ATTRVALUE} Length is out of range, bound is invalid, maxStringLength = {MAXLEN}, minStringLength = {MINLEN}",
152 "ATTRVALUE", attrValue, "MAXLEN", maxStringLength, "MINLEN",
153 minStringLength);
154 return false;
155 }
156
157 return true;
158}
159
160bool Manager::validateIntegerOption(
161 const int64_t& attrValue,
Arun Lal K M1a448ad2023-05-03 12:35:28 +0000162 const std::vector<std::tuple<BoundType, std::variant<int64_t, std::string>,
163 std::string>>& options)
yesad54c7c2022-12-29 22:38:32 +0530164{
165 int64_t lowerBound = 0;
166 int64_t upperBound = 0;
167 int64_t scalarIncrement = 0;
168
169 for (const auto& integerOptions : options)
170 {
171 if (BoundType::LowerBound == std::get<0>(integerOptions))
172 {
173 lowerBound = std::get<int64_t>(std::get<1>(integerOptions));
174 }
175 else if (BoundType::UpperBound == std::get<0>(integerOptions))
176 {
177 upperBound = std::get<int64_t>(std::get<1>(integerOptions));
178 }
179 else if (BoundType::ScalarIncrement == std::get<0>(integerOptions))
180 {
181 scalarIncrement = std::get<int64_t>(std::get<1>(integerOptions));
182 }
183 }
184
185 if ((attrValue < lowerBound) || (attrValue > upperBound))
186 {
187 lg2::error("Integer, bound is invalid");
188 return false;
189 }
190
191 if (scalarIncrement == 0 ||
192 ((std::abs(attrValue - lowerBound)) % scalarIncrement) != 0)
193 {
194 lg2::error(
195 "((std::abs({ATTR_VALUE} - {LOWER_BOUND})) % {SCALAR_INCREMENT}) != 0",
196 "ATTR_VALUE", attrValue, "LOWER_BOUND", lowerBound,
197 "SCALAR_INCREMENT", scalarIncrement);
198 return false;
199 }
200
201 return true;
202}
203
Kuiying Wang642f4372020-08-12 15:35:46 +0800204Manager::PendingAttributes Manager::pendingAttributes(PendingAttributes value)
205{
206 // Clear the pending attributes
207 if (value.empty())
208 {
Tom Josephf1101df2020-11-06 08:23:34 +0530209 auto pendingAttrs = Base::pendingAttributes({}, false);
210 serialize(*this, biosFile);
211 return pendingAttrs;
Kuiying Wang642f4372020-08-12 15:35:46 +0800212 }
213
214 // Validate all the BIOS attributes before setting PendingAttributes
215 BaseTable biosTable = Base::baseBIOSTable();
216 for (const auto& pair : value)
217 {
218 auto iter = biosTable.find(pair.first);
219 // BIOS attribute not found in the BaseBIOSTable
220 if (iter == biosTable.end())
221 {
George Liu567a3cf2021-12-08 10:36:03 +0800222 lg2::error("BIOS attribute not found in the BaseBIOSTable");
Kuiying Wang642f4372020-08-12 15:35:46 +0800223 throw AttributeNotFound();
224 }
225
Kuiying Wang642f4372020-08-12 15:35:46 +0800226 auto attributeType =
227 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
228 if (attributeType != std::get<0>(pair.second))
229 {
George Liu567a3cf2021-12-08 10:36:03 +0800230 lg2::error("attributeType is not same with bios base table");
Kuiying Wang642f4372020-08-12 15:35:46 +0800231 throw InvalidArgument();
232 }
233
234 // Validate enumeration BIOS attributes
235 if (attributeType == AttributeType::Enumeration)
236 {
Kuiying Wang8f706212020-12-16 18:59:24 +0800237 // For enumeration the expected variant types is Enumeration
Kuiying Wang642f4372020-08-12 15:35:46 +0800238 if (std::get<1>(pair.second).index() == 0)
239 {
George Liu567a3cf2021-12-08 10:36:03 +0800240 lg2::error("Enumeration property value is not enum");
Kuiying Wang642f4372020-08-12 15:35:46 +0800241 throw InvalidArgument();
242 }
243
244 const auto& attrValue =
245 std::get<std::string>(std::get<1>(pair.second));
246 const auto& options =
247 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
248
yesad54c7c2022-12-29 22:38:32 +0530249 if (!validateEnumOption(attrValue, options))
Kuiying Wang642f4372020-08-12 15:35:46 +0800250 {
Kuiying Wang642f4372020-08-12 15:35:46 +0800251 throw InvalidArgument();
252 }
253 }
254
255 if (attributeType == AttributeType::String)
256 {
257 // For enumeration the expected variant types is std::string
258 if (std::get<1>(pair.second).index() == 0)
259 {
George Liu567a3cf2021-12-08 10:36:03 +0800260 lg2::error("String property value is not string");
Kuiying Wang642f4372020-08-12 15:35:46 +0800261 throw InvalidArgument();
262 }
263
264 const auto& attrValue =
265 std::get<std::string>(std::get<1>(pair.second));
266 const auto& options =
267 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
Kuiying Wang642f4372020-08-12 15:35:46 +0800268
yesad54c7c2022-12-29 22:38:32 +0530269 if (!validateStringOption(attrValue, options))
Kuiying Wang642f4372020-08-12 15:35:46 +0800270 {
Kuiying Wang642f4372020-08-12 15:35:46 +0800271 throw InvalidArgument();
272 }
273 }
274
275 if (attributeType == AttributeType::Integer)
276 {
Kuiying Wang8f706212020-12-16 18:59:24 +0800277 // For enumeration the expected variant types is Integer
Kuiying Wang642f4372020-08-12 15:35:46 +0800278 if (std::get<1>(pair.second).index() == 1)
279 {
George Liu567a3cf2021-12-08 10:36:03 +0800280 lg2::error("Enumeration property value is not int");
Kuiying Wang642f4372020-08-12 15:35:46 +0800281 throw InvalidArgument();
282 }
283
284 const auto& attrValue = std::get<int64_t>(std::get<1>(pair.second));
285 const auto& options =
286 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
Kuiying Wang642f4372020-08-12 15:35:46 +0800287
yesad54c7c2022-12-29 22:38:32 +0530288 if (!validateIntegerOption(attrValue, options))
Kuiying Wang642f4372020-08-12 15:35:46 +0800289 {
Kuiying Wang642f4372020-08-12 15:35:46 +0800290 throw InvalidArgument();
291 }
292 }
293 }
294
295 PendingAttributes pendingAttribute = Base::pendingAttributes();
296
297 for (const auto& pair : value)
298 {
299 auto iter = pendingAttribute.find(pair.first);
300 if (iter != pendingAttribute.end())
301 {
302 iter = pendingAttribute.erase(iter);
303 }
304
305 pendingAttribute.emplace(std::make_pair(pair.first, pair.second));
306 }
307
Tom Josephf1101df2020-11-06 08:23:34 +0530308 auto pendingAttrs = Base::pendingAttributes(pendingAttribute, false);
309 serialize(*this, biosFile);
310
311 return pendingAttrs;
Kuiying Wang642f4372020-08-12 15:35:46 +0800312}
313
314Manager::Manager(sdbusplus::asio::object_server& objectServer,
Patrick Williams5c7e80d2024-10-18 21:24:12 -0400315 std::shared_ptr<sdbusplus::asio::connection>& systemBus,
316 std::string persistPath) :
Patrick Williamsea6a65f2024-08-16 15:19:44 -0400317 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager(
318 *systemBus, objectPath),
Kuiying Wang642f4372020-08-12 15:35:46 +0800319 objServer(objectServer), systemBus(systemBus)
Tom Josephf1101df2020-11-06 08:23:34 +0530320{
Patrick Williams5c7e80d2024-10-18 21:24:12 -0400321 fs::path biosDir(persistPath);
Tom Josephf1101df2020-11-06 08:23:34 +0530322 fs::create_directories(biosDir);
323 biosFile = biosDir / biosPersistFile;
324 deserialize(biosFile, *this);
325}
Kuiying Wang642f4372020-08-12 15:35:46 +0800326
327} // namespace bios_config