blob: e7d4c5efffe7f47672f2432c0d84c6ec42dc8dd0 [file] [log] [blame]
Sampa Misra032bd502019-03-06 05:03:22 -06001#include "bios.hpp"
2
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05003#include "common/utils.hpp"
Sampa Misra032bd502019-03-06 05:03:22 -06004
Xiaochao Ma60227a02019-12-04 09:00:12 +08005#include <time.h>
6
Sampa Misra032bd502019-03-06 05:03:22 -06007#include <array>
8#include <chrono>
9#include <ctime>
Sampa Misraaa8ae722019-12-12 03:20:40 -060010#include <iostream>
Sampa Misra032bd502019-03-06 05:03:22 -060011#include <stdexcept>
12#include <string>
13#include <variant>
14#include <vector>
15
16namespace pldm
17{
18
Sampa Misra032bd502019-03-06 05:03:22 -060019namespace responder
20{
21
22namespace utils
23{
24
25void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
26 uint8_t& hours, uint8_t& day, uint8_t& month,
27 uint16_t& year)
28{
29 auto t = time_t(timeSec);
30 auto time = localtime(&t);
31
George Liu83409572019-12-24 18:42:54 +080032 seconds = pldm::utils::decimalToBcd(time->tm_sec);
33 minutes = pldm::utils::decimalToBcd(time->tm_min);
34 hours = pldm::utils::decimalToBcd(time->tm_hour);
35 day = pldm::utils::decimalToBcd(time->tm_mday);
36 month = pldm::utils::decimalToBcd(time->tm_mon +
37 1); // The number of months in the range
38 // 0 to 11.PLDM expects range 1 to 12
39 year = pldm::utils::decimalToBcd(time->tm_year +
40 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060041}
42
Xiaochao Ma60227a02019-12-04 09:00:12 +080043std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
44 uint8_t day, uint8_t month, uint16_t year)
45{
46 struct std::tm stm;
47
48 stm.tm_year = year - 1900;
49 stm.tm_mon = month - 1;
50 stm.tm_mday = day;
51 stm.tm_hour = hours;
52 stm.tm_min = minutes;
53 stm.tm_sec = seconds;
54 stm.tm_isdst = -1;
55
56 // It will get the time in seconds since
57 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
58 return timegm(&stm);
59}
60
Sampa Misra032bd502019-03-06 05:03:22 -060061} // namespace utils
62
Deepak Kodihallibc669f12019-11-28 08:52:07 -060063namespace bios
64{
65
John Wang6080aae2020-02-14 09:34:25 +080066using EpochTimeUS = uint64_t;
67
68DBusHandler dbusHandler;
69
Sampa Misrac0c79482021-06-02 08:01:54 -050070Handler::Handler(int fd, uint8_t eid, dbus_api::Requester* requester,
71 pldm::requester::Handler<pldm::requester::Request>* handler) :
Tom Joseph7f839f92020-09-21 10:20:44 +053072 biosConfig(BIOS_JSONS_DIR, BIOS_TABLES_DIR, &dbusHandler, fd, eid,
Sampa Misrac0c79482021-06-02 08:01:54 -050073 requester, handler)
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060074{
John Wang6080aae2020-02-14 09:34:25 +080075 biosConfig.removeTables();
76 biosConfig.buildTables();
77
Xiaochao Ma60227a02019-12-04 09:00:12 +080078 handlers.emplace(PLDM_SET_DATE_TIME,
79 [this](const pldm_msg* request, size_t payloadLength) {
80 return this->setDateTime(request, payloadLength);
81 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060082 handlers.emplace(PLDM_GET_DATE_TIME,
83 [this](const pldm_msg* request, size_t payloadLength) {
84 return this->getDateTime(request, payloadLength);
85 });
86 handlers.emplace(PLDM_GET_BIOS_TABLE,
87 [this](const pldm_msg* request, size_t payloadLength) {
88 return this->getBIOSTable(request, payloadLength);
89 });
George Liu1b180d82020-07-23 14:01:58 +080090 handlers.emplace(PLDM_SET_BIOS_TABLE,
91 [this](const pldm_msg* request, size_t payloadLength) {
92 return this->setBIOSTable(request, payloadLength);
93 });
John Wang8721ed62019-12-05 14:44:43 +080094 handlers.emplace(PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
95 [this](const pldm_msg* request, size_t payloadLength) {
96 return this->getBIOSAttributeCurrentValueByHandle(
97 request, payloadLength);
98 });
John Wang42174882019-12-20 14:56:59 +080099 handlers.emplace(PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
100 [this](const pldm_msg* request, size_t payloadLength) {
101 return this->setBIOSAttributeCurrentValue(
102 request, payloadLength);
103 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600104}
105
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600106Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600107{
108 uint8_t seconds = 0;
109 uint8_t minutes = 0;
110 uint8_t hours = 0;
111 uint8_t day = 0;
112 uint8_t month = 0;
113 uint16_t year = 0;
114
115 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800116 constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
vkaverapa6575b82019-04-03 05:33:52 -0500117 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
118 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800119 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600120
Sampa Misra032bd502019-03-06 05:03:22 -0600121 try
122 {
George Liu782d37f2020-01-24 09:02:17 +0800123 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
George Liufd972642020-04-12 12:08:23 +0800124 bmcTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600125 }
George Liu0e02c322020-01-01 09:41:51 +0800126 catch (const sdbusplus::exception::SdBusError& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600127 {
George Liufd972642020-04-12 12:08:23 +0800128 std::cerr << "Error getting time, PATH=" << bmcTimePath
Sampa Misraaa8ae722019-12-12 03:20:40 -0600129 << " TIME INTERACE=" << timeInterface << "\n";
Sampa Misra032bd502019-03-06 05:03:22 -0600130
George Liufb8611d2019-12-06 10:14:15 +0800131 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600132 }
133
Sampa Misra032bd502019-03-06 05:03:22 -0600134 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
135 std::chrono::microseconds(timeUsec))
136 .count();
137
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600138 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
139 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600140
George Liufb8611d2019-12-06 10:14:15 +0800141 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
142 seconds, minutes, hours, day, month,
143 year, responsePtr);
144 if (rc != PLDM_SUCCESS)
145 {
146 return ccOnlyResponse(request, rc);
147 }
148
vkaverapa6575b82019-04-03 05:33:52 -0500149 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600150}
151
Xiaochao Ma60227a02019-12-04 09:00:12 +0800152Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
153{
154 uint8_t seconds = 0;
155 uint8_t minutes = 0;
156 uint8_t hours = 0;
157 uint8_t day = 0;
158 uint8_t month = 0;
159 uint16_t year = 0;
160 std::time_t timeSec;
161
162 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800163 constexpr auto setTimePath = "/xyz/openbmc_project/time/bmc";
Xiaochao Ma60227a02019-12-04 09:00:12 +0800164 constexpr auto timeSetPro = "Elapsed";
165
166 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
167 &minutes, &hours, &day, &month, &year);
168 if (rc != PLDM_SUCCESS)
169 {
170 return ccOnlyResponse(request, rc);
171 }
172 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
173 month, year);
174 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
175 std::chrono::seconds(timeSec))
176 .count();
George Liu1e44c732020-02-28 20:20:06 +0800177 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800178 try
179 {
George Liu1e44c732020-02-28 20:20:06 +0800180 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
181 "uint64_t"};
182 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800183 }
184 catch (std::exception& e)
185 {
186
187 std::cerr << "Error Setting time,PATH=" << setTimePath
188 << "TIME INTERFACE=" << setTimeInterface
189 << "ERROR=" << e.what() << "\n";
190
191 return ccOnlyResponse(request, PLDM_ERROR);
192 }
193
194 return ccOnlyResponse(request, PLDM_SUCCESS);
195}
196
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600197Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500198{
John Wang6080aae2020-02-14 09:34:25 +0800199 uint32_t transferHandle{};
200 uint8_t transferOpFlag{};
201 uint8_t tableType{};
202
203 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
204 &transferOpFlag, &tableType);
205 if (rc != PLDM_SUCCESS)
206 {
207 return ccOnlyResponse(request, rc);
208 }
209
210 auto table =
211 biosConfig.getBIOSTable(static_cast<pldm_bios_table_types>(tableType));
212 if (!table)
213 {
214 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
215 }
216
217 Response response(sizeof(pldm_msg_hdr) +
218 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + table->size());
219 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
220
221 rc = encode_get_bios_table_resp(
222 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
223 PLDM_START_AND_END, table->data(), response.size(), responsePtr);
224 if (rc != PLDM_SUCCESS)
225 {
226 return ccOnlyResponse(request, rc);
227 }
Sampa Misrab37be312019-07-03 02:26:41 -0500228
229 return response;
230}
231
George Liu1b180d82020-07-23 14:01:58 +0800232Response Handler::setBIOSTable(const pldm_msg* request, size_t payloadLength)
233{
234 uint32_t transferHandle{};
235 uint8_t transferOpFlag{};
236 uint8_t tableType{};
237 struct variable_field field;
238
239 auto rc = decode_set_bios_table_req(request, payloadLength, &transferHandle,
240 &transferOpFlag, &tableType, &field);
241 if (rc != PLDM_SUCCESS)
242 {
243 return ccOnlyResponse(request, rc);
244 }
245
246 Table table(field.ptr, field.ptr + field.length);
247 rc = biosConfig.setBIOSTable(tableType, table);
248 if (rc != PLDM_SUCCESS)
249 {
250 return ccOnlyResponse(request, rc);
251 }
252
253 Response response(sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_TABLE_RESP_BYTES);
254 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
255
256 rc = encode_set_bios_table_resp(request->hdr.instance_id, PLDM_SUCCESS,
257 0 /* nxtTransferHandle */, responsePtr);
258 if (rc != PLDM_SUCCESS)
259 {
260 return ccOnlyResponse(request, rc);
261 }
262
263 return response;
264}
265
John Wang8721ed62019-12-05 14:44:43 +0800266Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
267 size_t payloadLength)
268{
269 uint32_t transferHandle;
270 uint8_t transferOpFlag;
271 uint16_t attributeHandle;
272
273 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
274 request, payloadLength, &transferHandle, &transferOpFlag,
275 &attributeHandle);
276 if (rc != PLDM_SUCCESS)
277 {
278 return ccOnlyResponse(request, rc);
279 }
280
John Wang6080aae2020-02-14 09:34:25 +0800281 auto table = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
282 if (!table)
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600283 {
284 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
285 }
286
John Wang8721ed62019-12-05 14:44:43 +0800287 auto entry = pldm_bios_table_attr_value_find_by_handle(
John Wang6080aae2020-02-14 09:34:25 +0800288 table->data(), table->size(), attributeHandle);
John Wang8721ed62019-12-05 14:44:43 +0800289 if (entry == nullptr)
290 {
291 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
292 }
293
John Wang8e877e02020-02-03 16:06:55 +0800294 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800295 Response response(sizeof(pldm_msg_hdr) +
296 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800297 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800298 0);
299 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800300 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800301 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
302 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800303 if (rc != PLDM_SUCCESS)
304 {
305 return ccOnlyResponse(request, rc);
306 }
John Wang8721ed62019-12-05 14:44:43 +0800307
308 return response;
309}
310
John Wang42174882019-12-20 14:56:59 +0800311Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
312 size_t payloadLength)
313{
314 uint32_t transferHandle;
315 uint8_t transferOpFlag;
316 variable_field attributeField;
317
318 auto rc = decode_set_bios_attribute_current_value_req(
319 request, payloadLength, &transferHandle, &transferOpFlag,
320 &attributeField);
321 if (rc != PLDM_SUCCESS)
322 {
323 return ccOnlyResponse(request, rc);
324 }
325
John Wang6080aae2020-02-14 09:34:25 +0800326 rc = biosConfig.setAttrValue(attributeField.ptr, attributeField.length);
John Wang42174882019-12-20 14:56:59 +0800327
Xiaochao Ma7a0d0722020-05-29 09:07:33 +0800328 Response response(
329 sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES, 0);
330 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
331
332 encode_set_bios_attribute_current_value_resp(request->hdr.instance_id, rc,
333 0, responsePtr);
334
335 return response;
John Wang42174882019-12-20 14:56:59 +0800336}
337
John Wangf719f3b2020-01-17 08:46:22 +0800338} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -0600339} // namespace responder
340} // namespace pldm