blob: 39aad5b1a39b6b555fb10a980e3d8da69561e381 [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
Brad Bishop5079ac42021-08-19 18:35:06 -040016using namespace pldm::utils;
17
Sampa Misra032bd502019-03-06 05:03:22 -060018namespace pldm
19{
Sampa Misra032bd502019-03-06 05:03:22 -060020namespace responder
21{
Sampa Misra032bd502019-03-06 05:03:22 -060022namespace utils
23{
Sampa Misra032bd502019-03-06 05:03:22 -060024void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
25 uint8_t& hours, uint8_t& day, uint8_t& month,
26 uint16_t& year)
27{
28 auto t = time_t(timeSec);
29 auto time = localtime(&t);
30
George Liu83409572019-12-24 18:42:54 +080031 seconds = pldm::utils::decimalToBcd(time->tm_sec);
32 minutes = pldm::utils::decimalToBcd(time->tm_min);
33 hours = pldm::utils::decimalToBcd(time->tm_hour);
34 day = pldm::utils::decimalToBcd(time->tm_mday);
35 month = pldm::utils::decimalToBcd(time->tm_mon +
36 1); // The number of months in the range
37 // 0 to 11.PLDM expects range 1 to 12
38 year = pldm::utils::decimalToBcd(time->tm_year +
39 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060040}
41
Xiaochao Ma60227a02019-12-04 09:00:12 +080042std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
43 uint8_t day, uint8_t month, uint16_t year)
44{
45 struct std::tm stm;
46
47 stm.tm_year = year - 1900;
48 stm.tm_mon = month - 1;
49 stm.tm_mday = day;
50 stm.tm_hour = hours;
51 stm.tm_min = minutes;
52 stm.tm_sec = seconds;
53 stm.tm_isdst = -1;
54
55 // It will get the time in seconds since
56 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
57 return timegm(&stm);
58}
59
Sampa Misra032bd502019-03-06 05:03:22 -060060} // namespace utils
61
Deepak Kodihallibc669f12019-11-28 08:52:07 -060062namespace bios
63{
John Wang6080aae2020-02-14 09:34:25 +080064using EpochTimeUS = uint64_t;
65
66DBusHandler dbusHandler;
67
Sampa Misrac0c79482021-06-02 08:01:54 -050068Handler::Handler(int fd, uint8_t eid, dbus_api::Requester* requester,
69 pldm::requester::Handler<pldm::requester::Request>* handler) :
Tom Joseph7f839f92020-09-21 10:20:44 +053070 biosConfig(BIOS_JSONS_DIR, BIOS_TABLES_DIR, &dbusHandler, fd, eid,
Sampa Misrac0c79482021-06-02 08:01:54 -050071 requester, handler)
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060072{
John Wang6080aae2020-02-14 09:34:25 +080073 biosConfig.removeTables();
74 biosConfig.buildTables();
75
Xiaochao Ma60227a02019-12-04 09:00:12 +080076 handlers.emplace(PLDM_SET_DATE_TIME,
77 [this](const pldm_msg* request, size_t payloadLength) {
78 return this->setDateTime(request, payloadLength);
79 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060080 handlers.emplace(PLDM_GET_DATE_TIME,
81 [this](const pldm_msg* request, size_t payloadLength) {
82 return this->getDateTime(request, payloadLength);
83 });
84 handlers.emplace(PLDM_GET_BIOS_TABLE,
85 [this](const pldm_msg* request, size_t payloadLength) {
86 return this->getBIOSTable(request, payloadLength);
87 });
George Liu1b180d82020-07-23 14:01:58 +080088 handlers.emplace(PLDM_SET_BIOS_TABLE,
89 [this](const pldm_msg* request, size_t payloadLength) {
90 return this->setBIOSTable(request, payloadLength);
91 });
John Wang8721ed62019-12-05 14:44:43 +080092 handlers.emplace(PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
93 [this](const pldm_msg* request, size_t payloadLength) {
94 return this->getBIOSAttributeCurrentValueByHandle(
95 request, payloadLength);
96 });
John Wang42174882019-12-20 14:56:59 +080097 handlers.emplace(PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
98 [this](const pldm_msg* request, size_t payloadLength) {
99 return this->setBIOSAttributeCurrentValue(
100 request, payloadLength);
101 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600102}
103
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600104Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600105{
106 uint8_t seconds = 0;
107 uint8_t minutes = 0;
108 uint8_t hours = 0;
109 uint8_t day = 0;
110 uint8_t month = 0;
111 uint16_t year = 0;
112
113 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800114 constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
vkaverapa6575b82019-04-03 05:33:52 -0500115 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
116 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800117 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600118
Sampa Misra032bd502019-03-06 05:03:22 -0600119 try
120 {
George Liu782d37f2020-01-24 09:02:17 +0800121 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
George Liufd972642020-04-12 12:08:23 +0800122 bmcTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600123 }
Patrick Williams84b790c2022-07-22 19:26:56 -0500124 catch (const sdbusplus::exception_t& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600125 {
George Liufd972642020-04-12 12:08:23 +0800126 std::cerr << "Error getting time, PATH=" << bmcTimePath
Sampa Misraaa8ae722019-12-12 03:20:40 -0600127 << " TIME INTERACE=" << timeInterface << "\n";
Sampa Misra032bd502019-03-06 05:03:22 -0600128
George Liufb8611d2019-12-06 10:14:15 +0800129 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600130 }
131
Sampa Misra032bd502019-03-06 05:03:22 -0600132 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
133 std::chrono::microseconds(timeUsec))
134 .count();
135
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600136 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
137 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600138
George Liufb8611d2019-12-06 10:14:15 +0800139 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
140 seconds, minutes, hours, day, month,
141 year, responsePtr);
142 if (rc != PLDM_SUCCESS)
143 {
144 return ccOnlyResponse(request, rc);
145 }
146
vkaverapa6575b82019-04-03 05:33:52 -0500147 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600148}
149
Xiaochao Ma60227a02019-12-04 09:00:12 +0800150Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
151{
152 uint8_t seconds = 0;
153 uint8_t minutes = 0;
154 uint8_t hours = 0;
155 uint8_t day = 0;
156 uint8_t month = 0;
157 uint16_t year = 0;
158 std::time_t timeSec;
159
Pavithra Barithaya297720a2022-09-12 05:50:38 -0500160 constexpr auto timeSyncPath = "/xyz/openbmc_project/time/sync_method";
161 constexpr auto timeSyncInterface =
162 "xyz.openbmc_project.Time.Synchronization";
163 constexpr auto timeSyncProperty = "TimeSyncMethod";
164
165 // The time is correct on BMC when in NTP mode, so we do not want to
166 // try and set the time again and cause potential time drifts.
167 try
168 {
169 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant(
170 timeSyncPath, timeSyncProperty, timeSyncInterface);
171 const auto& mode = std::get<std::string>(propVal);
172
173 if (mode == "xyz.openbmc_project.Time.Synchronization.Method.NTP")
174 {
175 return ccOnlyResponse(request, PLDM_SUCCESS);
176 }
177 }
178 catch (const std::exception& e)
179 {
180 std::cerr << "Error getting the time sync property, PATH="
181 << timeSyncPath << "INTERFACE=" << timeSyncInterface
182 << "PROPERTY=" << timeSyncProperty << "ERROR=" << e.what()
183 << "\n";
184 }
185
Xiaochao Ma60227a02019-12-04 09:00:12 +0800186 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800187 constexpr auto setTimePath = "/xyz/openbmc_project/time/bmc";
Xiaochao Ma60227a02019-12-04 09:00:12 +0800188 constexpr auto timeSetPro = "Elapsed";
189
190 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
191 &minutes, &hours, &day, &month, &year);
192 if (rc != PLDM_SUCCESS)
193 {
194 return ccOnlyResponse(request, rc);
195 }
196 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
197 month, year);
198 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
199 std::chrono::seconds(timeSec))
200 .count();
George Liu1e44c732020-02-28 20:20:06 +0800201 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800202 try
203 {
George Liu1e44c732020-02-28 20:20:06 +0800204 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
205 "uint64_t"};
206 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800207 }
Patrick Williams51330582021-10-06 12:48:56 -0500208 catch (const std::exception& e)
Xiaochao Ma60227a02019-12-04 09:00:12 +0800209 {
Xiaochao Ma60227a02019-12-04 09:00:12 +0800210 std::cerr << "Error Setting time,PATH=" << setTimePath
211 << "TIME INTERFACE=" << setTimeInterface
212 << "ERROR=" << e.what() << "\n";
213
214 return ccOnlyResponse(request, PLDM_ERROR);
215 }
216
217 return ccOnlyResponse(request, PLDM_SUCCESS);
218}
219
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600220Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500221{
John Wang6080aae2020-02-14 09:34:25 +0800222 uint32_t transferHandle{};
223 uint8_t transferOpFlag{};
224 uint8_t tableType{};
225
226 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
227 &transferOpFlag, &tableType);
228 if (rc != PLDM_SUCCESS)
229 {
230 return ccOnlyResponse(request, rc);
231 }
232
233 auto table =
234 biosConfig.getBIOSTable(static_cast<pldm_bios_table_types>(tableType));
235 if (!table)
236 {
237 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
238 }
239
240 Response response(sizeof(pldm_msg_hdr) +
241 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + table->size());
242 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
243
244 rc = encode_get_bios_table_resp(
245 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
246 PLDM_START_AND_END, table->data(), response.size(), responsePtr);
247 if (rc != PLDM_SUCCESS)
248 {
249 return ccOnlyResponse(request, rc);
250 }
Sampa Misrab37be312019-07-03 02:26:41 -0500251
252 return response;
253}
254
George Liu1b180d82020-07-23 14:01:58 +0800255Response Handler::setBIOSTable(const pldm_msg* request, size_t payloadLength)
256{
257 uint32_t transferHandle{};
258 uint8_t transferOpFlag{};
259 uint8_t tableType{};
260 struct variable_field field;
261
262 auto rc = decode_set_bios_table_req(request, payloadLength, &transferHandle,
263 &transferOpFlag, &tableType, &field);
264 if (rc != PLDM_SUCCESS)
265 {
266 return ccOnlyResponse(request, rc);
267 }
268
269 Table table(field.ptr, field.ptr + field.length);
270 rc = biosConfig.setBIOSTable(tableType, table);
271 if (rc != PLDM_SUCCESS)
272 {
273 return ccOnlyResponse(request, rc);
274 }
275
276 Response response(sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_TABLE_RESP_BYTES);
277 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
278
279 rc = encode_set_bios_table_resp(request->hdr.instance_id, PLDM_SUCCESS,
280 0 /* nxtTransferHandle */, responsePtr);
281 if (rc != PLDM_SUCCESS)
282 {
283 return ccOnlyResponse(request, rc);
284 }
285
286 return response;
287}
288
John Wang8721ed62019-12-05 14:44:43 +0800289Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
290 size_t payloadLength)
291{
292 uint32_t transferHandle;
293 uint8_t transferOpFlag;
294 uint16_t attributeHandle;
295
296 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
297 request, payloadLength, &transferHandle, &transferOpFlag,
298 &attributeHandle);
299 if (rc != PLDM_SUCCESS)
300 {
301 return ccOnlyResponse(request, rc);
302 }
303
John Wang6080aae2020-02-14 09:34:25 +0800304 auto table = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
305 if (!table)
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600306 {
307 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
308 }
309
John Wang8721ed62019-12-05 14:44:43 +0800310 auto entry = pldm_bios_table_attr_value_find_by_handle(
John Wang6080aae2020-02-14 09:34:25 +0800311 table->data(), table->size(), attributeHandle);
John Wang8721ed62019-12-05 14:44:43 +0800312 if (entry == nullptr)
313 {
314 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
315 }
316
John Wang8e877e02020-02-03 16:06:55 +0800317 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800318 Response response(sizeof(pldm_msg_hdr) +
319 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800320 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800321 0);
322 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800323 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800324 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
325 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800326 if (rc != PLDM_SUCCESS)
327 {
328 return ccOnlyResponse(request, rc);
329 }
John Wang8721ed62019-12-05 14:44:43 +0800330
331 return response;
332}
333
John Wang42174882019-12-20 14:56:59 +0800334Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
335 size_t payloadLength)
336{
337 uint32_t transferHandle;
338 uint8_t transferOpFlag;
339 variable_field attributeField;
340
341 auto rc = decode_set_bios_attribute_current_value_req(
342 request, payloadLength, &transferHandle, &transferOpFlag,
343 &attributeField);
344 if (rc != PLDM_SUCCESS)
345 {
346 return ccOnlyResponse(request, rc);
347 }
348
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600349 rc = biosConfig.setAttrValue(attributeField.ptr, attributeField.length,
350 false);
John Wang42174882019-12-20 14:56:59 +0800351
Xiaochao Ma7a0d0722020-05-29 09:07:33 +0800352 Response response(
353 sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES, 0);
354 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
355
356 encode_set_bios_attribute_current_value_resp(request->hdr.instance_id, rc,
357 0, responsePtr);
358
359 return response;
John Wang42174882019-12-20 14:56:59 +0800360}
361
John Wangf719f3b2020-01-17 08:46:22 +0800362} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -0600363} // namespace responder
364} // namespace pldm