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