blob: fbe61443c9ce7986b6204495d86c4258af632d49 [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
Tom Joseph7f839f92020-09-21 10:20:44 +053070Handler::Handler(int fd, uint8_t eid, dbus_api::Requester* requester) :
71 biosConfig(BIOS_JSONS_DIR, BIOS_TABLES_DIR, &dbusHandler, fd, eid,
72 requester)
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060073{
John Wang6080aae2020-02-14 09:34:25 +080074 biosConfig.removeTables();
75 biosConfig.buildTables();
76
Xiaochao Ma60227a02019-12-04 09:00:12 +080077 handlers.emplace(PLDM_SET_DATE_TIME,
78 [this](const pldm_msg* request, size_t payloadLength) {
79 return this->setDateTime(request, payloadLength);
80 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060081 handlers.emplace(PLDM_GET_DATE_TIME,
82 [this](const pldm_msg* request, size_t payloadLength) {
83 return this->getDateTime(request, payloadLength);
84 });
85 handlers.emplace(PLDM_GET_BIOS_TABLE,
86 [this](const pldm_msg* request, size_t payloadLength) {
87 return this->getBIOSTable(request, payloadLength);
88 });
George Liu1b180d82020-07-23 14:01:58 +080089 handlers.emplace(PLDM_SET_BIOS_TABLE,
90 [this](const pldm_msg* request, size_t payloadLength) {
91 return this->setBIOSTable(request, payloadLength);
92 });
John Wang8721ed62019-12-05 14:44:43 +080093 handlers.emplace(PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
94 [this](const pldm_msg* request, size_t payloadLength) {
95 return this->getBIOSAttributeCurrentValueByHandle(
96 request, payloadLength);
97 });
John Wang42174882019-12-20 14:56:59 +080098 handlers.emplace(PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
99 [this](const pldm_msg* request, size_t payloadLength) {
100 return this->setBIOSAttributeCurrentValue(
101 request, payloadLength);
102 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600103}
104
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600105Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600106{
107 uint8_t seconds = 0;
108 uint8_t minutes = 0;
109 uint8_t hours = 0;
110 uint8_t day = 0;
111 uint8_t month = 0;
112 uint16_t year = 0;
113
114 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800115 constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
vkaverapa6575b82019-04-03 05:33:52 -0500116 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
117 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800118 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600119
Sampa Misra032bd502019-03-06 05:03:22 -0600120 try
121 {
George Liu782d37f2020-01-24 09:02:17 +0800122 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
George Liufd972642020-04-12 12:08:23 +0800123 bmcTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600124 }
George Liu0e02c322020-01-01 09:41:51 +0800125 catch (const sdbusplus::exception::SdBusError& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600126 {
George Liufd972642020-04-12 12:08:23 +0800127 std::cerr << "Error getting time, PATH=" << bmcTimePath
Sampa Misraaa8ae722019-12-12 03:20:40 -0600128 << " TIME INTERACE=" << timeInterface << "\n";
Sampa Misra032bd502019-03-06 05:03:22 -0600129
George Liufb8611d2019-12-06 10:14:15 +0800130 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600131 }
132
Sampa Misra032bd502019-03-06 05:03:22 -0600133 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
134 std::chrono::microseconds(timeUsec))
135 .count();
136
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600137 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
138 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600139
George Liufb8611d2019-12-06 10:14:15 +0800140 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
141 seconds, minutes, hours, day, month,
142 year, responsePtr);
143 if (rc != PLDM_SUCCESS)
144 {
145 return ccOnlyResponse(request, rc);
146 }
147
vkaverapa6575b82019-04-03 05:33:52 -0500148 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600149}
150
Xiaochao Ma60227a02019-12-04 09:00:12 +0800151Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
152{
153 uint8_t seconds = 0;
154 uint8_t minutes = 0;
155 uint8_t hours = 0;
156 uint8_t day = 0;
157 uint8_t month = 0;
158 uint16_t year = 0;
159 std::time_t timeSec;
160
161 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800162 constexpr auto setTimePath = "/xyz/openbmc_project/time/bmc";
Xiaochao Ma60227a02019-12-04 09:00:12 +0800163 constexpr auto timeSetPro = "Elapsed";
164
165 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
166 &minutes, &hours, &day, &month, &year);
167 if (rc != PLDM_SUCCESS)
168 {
169 return ccOnlyResponse(request, rc);
170 }
171 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
172 month, year);
173 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
174 std::chrono::seconds(timeSec))
175 .count();
George Liu1e44c732020-02-28 20:20:06 +0800176 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800177 try
178 {
George Liu1e44c732020-02-28 20:20:06 +0800179 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
180 "uint64_t"};
181 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800182 }
183 catch (std::exception& e)
184 {
185
186 std::cerr << "Error Setting time,PATH=" << setTimePath
187 << "TIME INTERFACE=" << setTimeInterface
188 << "ERROR=" << e.what() << "\n";
189
190 return ccOnlyResponse(request, PLDM_ERROR);
191 }
192
193 return ccOnlyResponse(request, PLDM_SUCCESS);
194}
195
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600196Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500197{
John Wang6080aae2020-02-14 09:34:25 +0800198 uint32_t transferHandle{};
199 uint8_t transferOpFlag{};
200 uint8_t tableType{};
201
202 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
203 &transferOpFlag, &tableType);
204 if (rc != PLDM_SUCCESS)
205 {
206 return ccOnlyResponse(request, rc);
207 }
208
209 auto table =
210 biosConfig.getBIOSTable(static_cast<pldm_bios_table_types>(tableType));
211 if (!table)
212 {
213 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
214 }
215
216 Response response(sizeof(pldm_msg_hdr) +
217 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + table->size());
218 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
219
220 rc = encode_get_bios_table_resp(
221 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
222 PLDM_START_AND_END, table->data(), response.size(), responsePtr);
223 if (rc != PLDM_SUCCESS)
224 {
225 return ccOnlyResponse(request, rc);
226 }
Sampa Misrab37be312019-07-03 02:26:41 -0500227
228 return response;
229}
230
George Liu1b180d82020-07-23 14:01:58 +0800231Response Handler::setBIOSTable(const pldm_msg* request, size_t payloadLength)
232{
233 uint32_t transferHandle{};
234 uint8_t transferOpFlag{};
235 uint8_t tableType{};
236 struct variable_field field;
237
238 auto rc = decode_set_bios_table_req(request, payloadLength, &transferHandle,
239 &transferOpFlag, &tableType, &field);
240 if (rc != PLDM_SUCCESS)
241 {
242 return ccOnlyResponse(request, rc);
243 }
244
245 Table table(field.ptr, field.ptr + field.length);
246 rc = biosConfig.setBIOSTable(tableType, table);
247 if (rc != PLDM_SUCCESS)
248 {
249 return ccOnlyResponse(request, rc);
250 }
251
252 Response response(sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_TABLE_RESP_BYTES);
253 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
254
255 rc = encode_set_bios_table_resp(request->hdr.instance_id, PLDM_SUCCESS,
256 0 /* nxtTransferHandle */, responsePtr);
257 if (rc != PLDM_SUCCESS)
258 {
259 return ccOnlyResponse(request, rc);
260 }
261
262 return response;
263}
264
John Wang8721ed62019-12-05 14:44:43 +0800265Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
266 size_t payloadLength)
267{
268 uint32_t transferHandle;
269 uint8_t transferOpFlag;
270 uint16_t attributeHandle;
271
272 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
273 request, payloadLength, &transferHandle, &transferOpFlag,
274 &attributeHandle);
275 if (rc != PLDM_SUCCESS)
276 {
277 return ccOnlyResponse(request, rc);
278 }
279
John Wang6080aae2020-02-14 09:34:25 +0800280 auto table = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
281 if (!table)
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600282 {
283 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
284 }
285
John Wang8721ed62019-12-05 14:44:43 +0800286 auto entry = pldm_bios_table_attr_value_find_by_handle(
John Wang6080aae2020-02-14 09:34:25 +0800287 table->data(), table->size(), attributeHandle);
John Wang8721ed62019-12-05 14:44:43 +0800288 if (entry == nullptr)
289 {
290 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
291 }
292
John Wang8e877e02020-02-03 16:06:55 +0800293 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800294 Response response(sizeof(pldm_msg_hdr) +
295 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800296 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800297 0);
298 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800299 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800300 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
301 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800302 if (rc != PLDM_SUCCESS)
303 {
304 return ccOnlyResponse(request, rc);
305 }
John Wang8721ed62019-12-05 14:44:43 +0800306
307 return response;
308}
309
John Wang42174882019-12-20 14:56:59 +0800310Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
311 size_t payloadLength)
312{
313 uint32_t transferHandle;
314 uint8_t transferOpFlag;
315 variable_field attributeField;
316
317 auto rc = decode_set_bios_attribute_current_value_req(
318 request, payloadLength, &transferHandle, &transferOpFlag,
319 &attributeField);
320 if (rc != PLDM_SUCCESS)
321 {
322 return ccOnlyResponse(request, rc);
323 }
324
John Wang6080aae2020-02-14 09:34:25 +0800325 rc = biosConfig.setAttrValue(attributeField.ptr, attributeField.length);
John Wang42174882019-12-20 14:56:59 +0800326
Xiaochao Ma7a0d0722020-05-29 09:07:33 +0800327 Response response(
328 sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES, 0);
329 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
330
331 encode_set_bios_attribute_current_value_resp(request->hdr.instance_id, rc,
332 0, responsePtr);
333
334 return response;
John Wang42174882019-12-20 14:56:59 +0800335}
336
John Wangf719f3b2020-01-17 08:46:22 +0800337} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -0600338} // namespace responder
339} // namespace pldm