blob: 1a6889885e8ec3b7899410c352fc98d414a8ceb8 [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
105Manager::PendingAttributes Manager::pendingAttributes(PendingAttributes value)
106{
107 // Clear the pending attributes
108 if (value.empty())
109 {
Tom Josephf1101df2020-11-06 08:23:34 +0530110 auto pendingAttrs = Base::pendingAttributes({}, false);
111 serialize(*this, biosFile);
112 return pendingAttrs;
Kuiying Wang642f4372020-08-12 15:35:46 +0800113 }
114
115 // Validate all the BIOS attributes before setting PendingAttributes
116 BaseTable biosTable = Base::baseBIOSTable();
117 for (const auto& pair : value)
118 {
119 auto iter = biosTable.find(pair.first);
120 // BIOS attribute not found in the BaseBIOSTable
121 if (iter == biosTable.end())
122 {
George Liu567a3cf2021-12-08 10:36:03 +0800123 lg2::error("BIOS attribute not found in the BaseBIOSTable");
Kuiying Wang642f4372020-08-12 15:35:46 +0800124 throw AttributeNotFound();
125 }
126
Kuiying Wang642f4372020-08-12 15:35:46 +0800127 auto attributeType =
128 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
129 if (attributeType != std::get<0>(pair.second))
130 {
George Liu567a3cf2021-12-08 10:36:03 +0800131 lg2::error("attributeType is not same with bios base table");
Kuiying Wang642f4372020-08-12 15:35:46 +0800132 throw InvalidArgument();
133 }
134
135 // Validate enumeration BIOS attributes
136 if (attributeType == AttributeType::Enumeration)
137 {
Kuiying Wang8f706212020-12-16 18:59:24 +0800138 // For enumeration the expected variant types is Enumeration
Kuiying Wang642f4372020-08-12 15:35:46 +0800139 if (std::get<1>(pair.second).index() == 0)
140 {
George Liu567a3cf2021-12-08 10:36:03 +0800141 lg2::error("Enumeration property value is not enum");
Kuiying Wang642f4372020-08-12 15:35:46 +0800142 throw InvalidArgument();
143 }
144
145 const auto& attrValue =
146 std::get<std::string>(std::get<1>(pair.second));
147 const auto& options =
148 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
149
150 bool found = false;
151 for (const auto& enumOptions : options)
152 {
153 if ((BoundType::OneOf == std::get<0>(enumOptions)) &&
154 (attrValue ==
155 std::get<std::string>(std::get<1>(enumOptions))))
156 {
157 found = true;
158 break;
159 }
160 }
161
162 if (!found)
163 {
George Liu567a3cf2021-12-08 10:36:03 +0800164 lg2::error("No valid attribute");
Kuiying Wang642f4372020-08-12 15:35:46 +0800165 throw InvalidArgument();
166 }
167 }
168
169 if (attributeType == AttributeType::String)
170 {
171 // For enumeration the expected variant types is std::string
172 if (std::get<1>(pair.second).index() == 0)
173 {
George Liu567a3cf2021-12-08 10:36:03 +0800174 lg2::error("String property value is not string");
Kuiying Wang642f4372020-08-12 15:35:46 +0800175 throw InvalidArgument();
176 }
177
178 const auto& attrValue =
179 std::get<std::string>(std::get<1>(pair.second));
180 const auto& options =
181 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
Kuiying Wang642f4372020-08-12 15:35:46 +0800182
George Liu47453d72021-11-29 16:58:10 +0800183 size_t minStringLength = 0;
184 size_t maxStringLength = 0;
185 for (const auto& stringOptions : options)
Kuiying Wang642f4372020-08-12 15:35:46 +0800186 {
George Liu47453d72021-11-29 16:58:10 +0800187 if (BoundType::MinStringLength == std::get<0>(stringOptions))
Kuiying Wang642f4372020-08-12 15:35:46 +0800188 {
George Liu47453d72021-11-29 16:58:10 +0800189 minStringLength =
190 std::get<int64_t>(std::get<1>(stringOptions));
191 }
192 else if (BoundType::MaxStringLength ==
193 std::get<0>(stringOptions))
194 {
195 maxStringLength =
196 std::get<int64_t>(std::get<1>(stringOptions));
197 }
198 else
199 {
200 continue;
Kuiying Wang642f4372020-08-12 15:35:46 +0800201 }
202 }
203
George Liu47453d72021-11-29 16:58:10 +0800204 if (attrValue.length() < minStringLength ||
205 attrValue.length() > maxStringLength)
Kuiying Wang642f4372020-08-12 15:35:46 +0800206 {
George Liu47453d72021-11-29 16:58:10 +0800207 lg2::error(
208 "{ATTRVALUE} Length is out of range, bound is invalid, maxStringLength = {MAXLEN}, minStringLength = {MINLEN}",
209 "ATTRVALUE", attrValue, "MAXLEN", maxStringLength, "MINLEN",
210 minStringLength);
Kuiying Wang642f4372020-08-12 15:35:46 +0800211 throw InvalidArgument();
212 }
213 }
214
215 if (attributeType == AttributeType::Integer)
216 {
Kuiying Wang8f706212020-12-16 18:59:24 +0800217 // For enumeration the expected variant types is Integer
Kuiying Wang642f4372020-08-12 15:35:46 +0800218 if (std::get<1>(pair.second).index() == 1)
219 {
George Liu567a3cf2021-12-08 10:36:03 +0800220 lg2::error("Enumeration property value is not int");
Kuiying Wang642f4372020-08-12 15:35:46 +0800221 throw InvalidArgument();
222 }
223
224 const auto& attrValue = std::get<int64_t>(std::get<1>(pair.second));
225 const auto& options =
226 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
227 int64_t lowerBound = 0;
228 int64_t upperBound = 0;
229 int64_t scalarIncrement = 0;
230
231 for (const auto& integerOptions : options)
232 {
233 if (BoundType::LowerBound == std::get<0>(integerOptions))
234 {
235 lowerBound = std::get<int64_t>(std::get<1>(integerOptions));
236 }
237 else if (BoundType::UpperBound == std::get<0>(integerOptions))
238 {
239 upperBound = std::get<int64_t>(std::get<1>(integerOptions));
240 }
241 else if (BoundType::ScalarIncrement ==
242 std::get<0>(integerOptions))
243 {
244 scalarIncrement =
245 std::get<int64_t>(std::get<1>(integerOptions));
246 }
247 }
248
249 if ((attrValue < lowerBound) || (attrValue > upperBound))
250 {
George Liu567a3cf2021-12-08 10:36:03 +0800251 lg2::error("Integer, bound is invalid");
Kuiying Wang642f4372020-08-12 15:35:46 +0800252 throw InvalidArgument();
253 }
254
George Liu616f9222021-12-29 14:25:39 +0800255 if (scalarIncrement == 0 ||
256 ((std::abs(attrValue - lowerBound)) % scalarIncrement) != 0)
Kuiying Wang642f4372020-08-12 15:35:46 +0800257 {
George Liu567a3cf2021-12-08 10:36:03 +0800258 lg2::error(
259 "((std::abs({ATTR_VALUE} - {LOWER_BOUND})) % {SCALAR_INCREMENT}) != 0",
260 "ATTR_VALUE", attrValue, "LOWER_BOUND", lowerBound,
261 "SCALAR_INCREMENT", scalarIncrement);
Kuiying Wang642f4372020-08-12 15:35:46 +0800262 throw InvalidArgument();
263 }
264 }
265 }
266
267 PendingAttributes pendingAttribute = Base::pendingAttributes();
268
269 for (const auto& pair : value)
270 {
271 auto iter = pendingAttribute.find(pair.first);
272 if (iter != pendingAttribute.end())
273 {
274 iter = pendingAttribute.erase(iter);
275 }
276
277 pendingAttribute.emplace(std::make_pair(pair.first, pair.second));
278 }
279
Tom Josephf1101df2020-11-06 08:23:34 +0530280 auto pendingAttrs = Base::pendingAttributes(pendingAttribute, false);
281 serialize(*this, biosFile);
282
283 return pendingAttrs;
Kuiying Wang642f4372020-08-12 15:35:46 +0800284}
285
286Manager::Manager(sdbusplus::asio::object_server& objectServer,
287 std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
288 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager(*systemBus,
289 objectPath),
290 objServer(objectServer), systemBus(systemBus)
Tom Josephf1101df2020-11-06 08:23:34 +0530291{
292 fs::path biosDir(BIOS_PERSIST_PATH);
293 fs::create_directories(biosDir);
294 biosFile = biosDir / biosPersistFile;
295 deserialize(biosFile, *this);
296}
Kuiying Wang642f4372020-08-12 15:35:46 +0800297
298} // namespace bios_config
299
300int main()
301{
302 boost::asio::io_service io;
303 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
304
305 systemBus->request_name(bios_config::service);
306 sdbusplus::asio::object_server objectServer(systemBus);
307 bios_config::Manager manager(objectServer, systemBus);
308
309 io.run();
310 return 0;
311}