blob: c4c660de998562b80494cb31a3a92e1cb8ea77da [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
18#include "xyz/openbmc_project/BIOSConfig/Common/error.hpp"
19#include "xyz/openbmc_project/Common/error.hpp"
20
21#include <boost/asio.hpp>
22#include <sdbusplus/asio/connection.hpp>
23#include <sdbusplus/asio/object_server.hpp>
24
25namespace bios_config
26{
27
28using namespace sdbusplus::xyz::openbmc_project::Common::Error;
29using namespace sdbusplus::xyz::openbmc_project::BIOSConfig::Common::Error;
30
31void Manager::setAttribute(AttributeName attribute, AttributeValue value)
32{
33 auto pendingAttrs = Base::pendingAttributes();
34 auto iter = pendingAttrs.find(attribute);
35
36 if (iter != pendingAttrs.end())
37 {
38 std::get<1>(iter->second) = value;
39 }
40 else
41 {
42 Manager::PendingAttribute attributeValue;
43
44 if (std::get_if<int64_t>(&value))
45 {
46 std::get<0>(attributeValue) = AttributeType::Integer;
47 }
48 else
49 {
50 std::get<0>(attributeValue) = AttributeType::String;
51 }
52
53 std::get<1>(attributeValue) = value;
54 pendingAttrs.emplace(attribute, attributeValue);
55 }
56
57 pendingAttributes(pendingAttrs);
58}
59
60Manager::AttributeDetails Manager::getAttribute(AttributeName attribute)
61{
62 Manager::AttributeDetails value;
63
64 auto table = Base::baseBIOSTable();
65 auto iter = table.find(attribute);
66
67 if (iter != table.end())
68 {
69 std::get<0>(value) =
70 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
71 std::get<1>(value) =
72 std::get<static_cast<uint8_t>(Index::currentValue)>(iter->second);
73
74 auto pending = Base::pendingAttributes();
75 auto pendingIter = pending.find(attribute);
76 if (pendingIter != pending.end())
77 {
78 std::get<2>(value) = std::get<1>(pendingIter->second);
79 }
80 else if (std::get_if<std::string>(&std::get<1>(value)))
81 {
82 std::get<2>(value) = std::string();
83 }
84 }
85 else
86 {
87 throw AttributeNotFound();
88 }
89
90 return value;
91}
92
93Manager::BaseTable Manager::baseBIOSTable(BaseTable value)
94{
95 pendingAttributes({});
96 return Base::baseBIOSTable(value, false);
97}
98
99Manager::PendingAttributes Manager::pendingAttributes(PendingAttributes value)
100{
101 // Clear the pending attributes
102 if (value.empty())
103 {
104 return Base::pendingAttributes({}, false);
105 }
106
107 // Validate all the BIOS attributes before setting PendingAttributes
108 BaseTable biosTable = Base::baseBIOSTable();
109 for (const auto& pair : value)
110 {
111 auto iter = biosTable.find(pair.first);
112 // BIOS attribute not found in the BaseBIOSTable
113 if (iter == biosTable.end())
114 {
115 throw AttributeNotFound();
116 }
117
118 // BIOS attribute is read only
119 if (std::get<static_cast<uint8_t>(Index::readOnly)>(iter->second))
120 {
121 throw AttributeReadOnly();
122 }
123
124 auto attributeType =
125 std::get<static_cast<uint8_t>(Index::attributeType)>(iter->second);
126 if (attributeType != std::get<0>(pair.second))
127 {
128 throw InvalidArgument();
129 }
130
131 // Validate enumeration BIOS attributes
132 if (attributeType == AttributeType::Enumeration)
133 {
134 // For enumeration the expected variant types is std::string
135 if (std::get<1>(pair.second).index() == 0)
136 {
137 throw InvalidArgument();
138 }
139
140 const auto& attrValue =
141 std::get<std::string>(std::get<1>(pair.second));
142 const auto& options =
143 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
144
145 bool found = false;
146 for (const auto& enumOptions : options)
147 {
148 if ((BoundType::OneOf == std::get<0>(enumOptions)) &&
149 (attrValue ==
150 std::get<std::string>(std::get<1>(enumOptions))))
151 {
152 found = true;
153 break;
154 }
155 }
156
157 if (!found)
158 {
159 throw InvalidArgument();
160 }
161 }
162
163 if (attributeType == AttributeType::String)
164 {
165 // For enumeration the expected variant types is std::string
166 if (std::get<1>(pair.second).index() == 0)
167 {
168 throw InvalidArgument();
169 }
170
171 const auto& attrValue =
172 std::get<std::string>(std::get<1>(pair.second));
173 const auto& options =
174 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
175 int64_t minStringLength = 0;
176 int64_t maxStringLength = 0;
177
178 for (const auto& stringOptions : options)
179 {
180 if (BoundType::MinStringLength == std::get<0>(stringOptions))
181 {
182 minStringLength =
183 std::get<int64_t>(std::get<1>(stringOptions));
184 }
185 else if (BoundType::MaxStringLength ==
186 std::get<0>(stringOptions))
187 {
188 maxStringLength =
189 std::get<int64_t>(std::get<1>(stringOptions));
190 }
191 }
192
193 if ((attrValue.length() < static_cast<size_t>(minStringLength)) ||
194 (attrValue.length() > static_cast<size_t>(maxStringLength)))
195 {
196 throw InvalidArgument();
197 }
198 }
199
200 if (attributeType == AttributeType::Integer)
201 {
202 // For enumeration the expected variant types is std::string
203 if (std::get<1>(pair.second).index() == 1)
204 {
205 throw InvalidArgument();
206 }
207
208 const auto& attrValue = std::get<int64_t>(std::get<1>(pair.second));
209 const auto& options =
210 std::get<static_cast<uint8_t>(Index::options)>(iter->second);
211 int64_t lowerBound = 0;
212 int64_t upperBound = 0;
213 int64_t scalarIncrement = 0;
214
215 for (const auto& integerOptions : options)
216 {
217 if (BoundType::LowerBound == std::get<0>(integerOptions))
218 {
219 lowerBound = std::get<int64_t>(std::get<1>(integerOptions));
220 }
221 else if (BoundType::UpperBound == std::get<0>(integerOptions))
222 {
223 upperBound = std::get<int64_t>(std::get<1>(integerOptions));
224 }
225 else if (BoundType::ScalarIncrement ==
226 std::get<0>(integerOptions))
227 {
228 scalarIncrement =
229 std::get<int64_t>(std::get<1>(integerOptions));
230 }
231 }
232
233 if ((attrValue < lowerBound) || (attrValue > upperBound))
234 {
235 throw InvalidArgument();
236 }
237
238 if (((std::abs(attrValue - lowerBound)) % scalarIncrement) != 0)
239 {
240 throw InvalidArgument();
241 }
242 }
243 }
244
245 PendingAttributes pendingAttribute = Base::pendingAttributes();
246
247 for (const auto& pair : value)
248 {
249 auto iter = pendingAttribute.find(pair.first);
250 if (iter != pendingAttribute.end())
251 {
252 iter = pendingAttribute.erase(iter);
253 }
254
255 pendingAttribute.emplace(std::make_pair(pair.first, pair.second));
256 }
257
258 return Base::pendingAttributes(pendingAttribute, false);
259}
260
261Manager::Manager(sdbusplus::asio::object_server& objectServer,
262 std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
263 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager(*systemBus,
264 objectPath),
265 objServer(objectServer), systemBus(systemBus)
266{}
267
268} // namespace bios_config
269
270int main()
271{
272 boost::asio::io_service io;
273 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
274
275 systemBus->request_name(bios_config::service);
276 sdbusplus::asio::object_server objectServer(systemBus);
277 bios_config::Manager manager(objectServer, systemBus);
278
279 io.run();
280 return 0;
281}