blob: fa619a849c79f6d90c440ca9cab1ade4d0f70996 [file] [log] [blame]
Kuiying Wang642f4372020-08-12 15:35:46 +08001/*
2// 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.
15*/
16#include "manager.hpp"
17
Tom Josephf1101df2020-11-06 08:23:34 +053018#include "manager_serialize.hpp"
Kuiying Wang642f4372020-08-12 15:35:46 +080019#include "xyz/openbmc_project/BIOSConfig/Common/error.hpp"
20#include "xyz/openbmc_project/Common/error.hpp"
21
22#include <boost/asio.hpp>
Kuiying Wang8f706212020-12-16 18:59:24 +080023#include <phosphor-logging/elog-errors.hpp>
George Liu567a3cf2021-12-08 10:36:03 +080024#include <phosphor-logging/lg2.hpp>
Kuiying Wang642f4372020-08-12 15:35:46 +080025#include <sdbusplus/asio/connection.hpp>
26#include <sdbusplus/asio/object_server.hpp>
27
28namespace bios_config
29{
30
31using namespace sdbusplus::xyz::openbmc_project::Common::Error;
32using namespace sdbusplus::xyz::openbmc_project::BIOSConfig::Common::Error;
33
34void Manager::setAttribute(AttributeName attribute, AttributeValue value)
35{
36 auto pendingAttrs = Base::pendingAttributes();
37 auto iter = pendingAttrs.find(attribute);
38
39 if (iter != pendingAttrs.end())
40 {
41 std::get<1>(iter->second) = value;
42 }
43 else
44 {
45 Manager::PendingAttribute attributeValue;
46
47 if (std::get_if<int64_t>(&value))
48 {
49 std::get<0>(attributeValue) = AttributeType::Integer;
50 }
51 else
52 {
53 std::get<0>(attributeValue) = AttributeType::String;
54 }
55
56 std::get<1>(attributeValue) = value;
57 pendingAttrs.emplace(attribute, attributeValue);
58 }
59
60 pendingAttributes(pendingAttrs);
61}
62
63Manager::AttributeDetails Manager::getAttribute(AttributeName attribute)
64{
65 Manager::AttributeDetails value;
66
67 auto table = Base::baseBIOSTable();
68 auto iter = table.find(attribute);
69
70 if (iter != table.end())
71 {
72 std::get<0>(value) =
73 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
74 std::get<1>(value) =
75 std::get<static_cast<uint8_t>(Index::currentValue)>(iter->second);
76
77 auto pending = Base::pendingAttributes();
78 auto pendingIter = pending.find(attribute);
79 if (pendingIter != pending.end())
80 {
81 std::get<2>(value) = std::get<1>(pendingIter->second);
82 }
83 else if (std::get_if<std::string>(&std::get<1>(value)))
84 {
85 std::get<2>(value) = std::string();
86 }
87 }
88 else
89 {
90 throw AttributeNotFound();
91 }
92
93 return value;
94}
95
96Manager::BaseTable Manager::baseBIOSTable(BaseTable value)
97{
98 pendingAttributes({});
Tom Josephf1101df2020-11-06 08:23:34 +053099 auto baseTable = Base::baseBIOSTable(value, false);
100 serialize(*this, biosFile);
Snehalatha Venkatesh5e2cb722021-05-26 10:42:58 +0000101 Base::resetBIOSSettings(Base::ResetFlag::NoAction);
Tom Josephf1101df2020-11-06 08:23:34 +0530102 return baseTable;
Kuiying Wang642f4372020-08-12 15:35:46 +0800103}
104
yesad54c7c2022-12-29 22:38:32 +0530105bool Manager::validateEnumOption(
106 const std::string& attrValue,
107 const std::vector<
108 std::tuple<BoundType, std::variant<int64_t, std::string>>>& options)
109{
110 for (const auto& enumOptions : options)
111 {
112 if ((BoundType::OneOf == std::get<0>(enumOptions)) &&
113 (attrValue == std::get<std::string>(std::get<1>(enumOptions))))
114 {
115 return true;
116 }
117 }
118
119 lg2::error("No valid attribute");
120 return false;
121}
122
123bool Manager::validateStringOption(
124 const std::string& attrValue,
125 const std::vector<
126 std::tuple<BoundType, std::variant<int64_t, std::string>>>& options)
127{
128 size_t minStringLength = 0;
129 size_t maxStringLength = 0;
130 for (const auto& stringOptions : options)
131 {
132 if (BoundType::MinStringLength == std::get<0>(stringOptions))
133 {
134 minStringLength = std::get<int64_t>(std::get<1>(stringOptions));
135 }
136 else if (BoundType::MaxStringLength == std::get<0>(stringOptions))
137 {
138 maxStringLength = std::get<int64_t>(std::get<1>(stringOptions));
139 }
140 else
141 {
142 continue;
143 }
144 }
145
146 if (attrValue.length() < minStringLength ||
147 attrValue.length() > maxStringLength)
148 {
149 lg2::error(
150 "{ATTRVALUE} Length is out of range, bound is invalid, maxStringLength = {MAXLEN}, minStringLength = {MINLEN}",
151 "ATTRVALUE", attrValue, "MAXLEN", maxStringLength, "MINLEN",
152 minStringLength);
153 return false;
154 }
155
156 return true;
157}
158
159bool Manager::validateIntegerOption(
160 const int64_t& attrValue,
161 const std::vector<
162 std::tuple<BoundType, std::variant<int64_t, std::string>>>& options)
163{
164 int64_t lowerBound = 0;
165 int64_t upperBound = 0;
166 int64_t scalarIncrement = 0;
167
168 for (const auto& integerOptions : options)
169 {
170 if (BoundType::LowerBound == std::get<0>(integerOptions))
171 {
172 lowerBound = std::get<int64_t>(std::get<1>(integerOptions));
173 }
174 else if (BoundType::UpperBound == std::get<0>(integerOptions))
175 {
176 upperBound = std::get<int64_t>(std::get<1>(integerOptions));
177 }
178 else if (BoundType::ScalarIncrement == std::get<0>(integerOptions))
179 {
180 scalarIncrement = std::get<int64_t>(std::get<1>(integerOptions));
181 }
182 }
183
184 if ((attrValue < lowerBound) || (attrValue > upperBound))
185 {
186 lg2::error("Integer, bound is invalid");
187 return false;
188 }
189
190 if (scalarIncrement == 0 ||
191 ((std::abs(attrValue - lowerBound)) % scalarIncrement) != 0)
192 {
193 lg2::error(
194 "((std::abs({ATTR_VALUE} - {LOWER_BOUND})) % {SCALAR_INCREMENT}) != 0",
195 "ATTR_VALUE", attrValue, "LOWER_BOUND", lowerBound,
196 "SCALAR_INCREMENT", scalarIncrement);
197 return false;
198 }
199
200 return true;
201}
202
Kuiying Wang642f4372020-08-12 15:35:46 +0800203Manager::PendingAttributes Manager::pendingAttributes(PendingAttributes value)
204{
205 // Clear the pending attributes
206 if (value.empty())
207 {
Tom Josephf1101df2020-11-06 08:23:34 +0530208 auto pendingAttrs = Base::pendingAttributes({}, false);
209 serialize(*this, biosFile);
210 return pendingAttrs;
Kuiying Wang642f4372020-08-12 15:35:46 +0800211 }
212
213 // Validate all the BIOS attributes before setting PendingAttributes
214 BaseTable biosTable = Base::baseBIOSTable();
215 for (const auto& pair : value)
216 {
217 auto iter = biosTable.find(pair.first);
218 // BIOS attribute not found in the BaseBIOSTable
219 if (iter == biosTable.end())
220 {
George Liu567a3cf2021-12-08 10:36:03 +0800221 lg2::error("BIOS attribute not found in the BaseBIOSTable");
Kuiying Wang642f4372020-08-12 15:35:46 +0800222 throw AttributeNotFound();
223 }
224
Kuiying Wang642f4372020-08-12 15:35:46 +0800225 auto attributeType =
226 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
227 if (attributeType != std::get<0>(pair.second))
228 {
George Liu567a3cf2021-12-08 10:36:03 +0800229 lg2::error("attributeType is not same with bios base table");
Kuiying Wang642f4372020-08-12 15:35:46 +0800230 throw InvalidArgument();
231 }
232
233 // Validate enumeration BIOS attributes
234 if (attributeType == AttributeType::Enumeration)
235 {
Kuiying Wang8f706212020-12-16 18:59:24 +0800236 // For enumeration the expected variant types is Enumeration
Kuiying Wang642f4372020-08-12 15:35:46 +0800237 if (std::get<1>(pair.second).index() == 0)
238 {
George Liu567a3cf2021-12-08 10:36:03 +0800239 lg2::error("Enumeration property value is not enum");
Kuiying Wang642f4372020-08-12 15:35:46 +0800240 throw InvalidArgument();
241 }
242
243 const auto& attrValue =
244 std::get<std::string>(std::get<1>(pair.second));
245 const auto& options =
246 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
247
yesad54c7c2022-12-29 22:38:32 +0530248 if (!validateEnumOption(attrValue, options))
Kuiying Wang642f4372020-08-12 15:35:46 +0800249 {
Kuiying Wang642f4372020-08-12 15:35:46 +0800250 throw InvalidArgument();
251 }
252 }
253
254 if (attributeType == AttributeType::String)
255 {
256 // For enumeration the expected variant types is std::string
257 if (std::get<1>(pair.second).index() == 0)
258 {
George Liu567a3cf2021-12-08 10:36:03 +0800259 lg2::error("String property value is not string");
Kuiying Wang642f4372020-08-12 15:35:46 +0800260 throw InvalidArgument();
261 }
262
263 const auto& attrValue =
264 std::get<std::string>(std::get<1>(pair.second));
265 const auto& options =
266 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
Kuiying Wang642f4372020-08-12 15:35:46 +0800267
yesad54c7c2022-12-29 22:38:32 +0530268 if (!validateStringOption(attrValue, options))
Kuiying Wang642f4372020-08-12 15:35:46 +0800269 {
Kuiying Wang642f4372020-08-12 15:35:46 +0800270 throw InvalidArgument();
271 }
272 }
273
274 if (attributeType == AttributeType::Integer)
275 {
Kuiying Wang8f706212020-12-16 18:59:24 +0800276 // For enumeration the expected variant types is Integer
Kuiying Wang642f4372020-08-12 15:35:46 +0800277 if (std::get<1>(pair.second).index() == 1)
278 {
George Liu567a3cf2021-12-08 10:36:03 +0800279 lg2::error("Enumeration property value is not int");
Kuiying Wang642f4372020-08-12 15:35:46 +0800280 throw InvalidArgument();
281 }
282
283 const auto& attrValue = std::get<int64_t>(std::get<1>(pair.second));
284 const auto& options =
285 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
Kuiying Wang642f4372020-08-12 15:35:46 +0800286
yesad54c7c2022-12-29 22:38:32 +0530287 if (!validateIntegerOption(attrValue, options))
Kuiying Wang642f4372020-08-12 15:35:46 +0800288 {
Kuiying Wang642f4372020-08-12 15:35:46 +0800289 throw InvalidArgument();
290 }
291 }
292 }
293
294 PendingAttributes pendingAttribute = Base::pendingAttributes();
295
296 for (const auto& pair : value)
297 {
298 auto iter = pendingAttribute.find(pair.first);
299 if (iter != pendingAttribute.end())
300 {
301 iter = pendingAttribute.erase(iter);
302 }
303
304 pendingAttribute.emplace(std::make_pair(pair.first, pair.second));
305 }
306
Tom Josephf1101df2020-11-06 08:23:34 +0530307 auto pendingAttrs = Base::pendingAttributes(pendingAttribute, false);
308 serialize(*this, biosFile);
309
310 return pendingAttrs;
Kuiying Wang642f4372020-08-12 15:35:46 +0800311}
312
313Manager::Manager(sdbusplus::asio::object_server& objectServer,
314 std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
315 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager(*systemBus,
316 objectPath),
317 objServer(objectServer), systemBus(systemBus)
Tom Josephf1101df2020-11-06 08:23:34 +0530318{
319 fs::path biosDir(BIOS_PERSIST_PATH);
320 fs::create_directories(biosDir);
321 biosFile = biosDir / biosPersistFile;
322 deserialize(biosFile, *this);
323}
Kuiying Wang642f4372020-08-12 15:35:46 +0800324
325} // namespace bios_config