blob: 637b2135d764a68dad4ad0f3318bc5264656d848 [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
Riya Dixit49cfb132023-03-02 04:26:53 -06007#include <phosphor-logging/lg2.hpp>
8
Sampa Misra032bd502019-03-06 05:03:22 -06009#include <array>
10#include <chrono>
11#include <ctime>
Sampa Misraaa8ae722019-12-12 03:20:40 -060012#include <iostream>
Sampa Misra032bd502019-03-06 05:03:22 -060013#include <stdexcept>
14#include <string>
15#include <variant>
16#include <vector>
17
Riya Dixit49cfb132023-03-02 04:26:53 -060018PHOSPHOR_LOG2_USING;
19
Brad Bishop5079ac42021-08-19 18:35:06 -040020using namespace pldm::utils;
21
Sampa Misra032bd502019-03-06 05:03:22 -060022namespace pldm
23{
Sampa Misra032bd502019-03-06 05:03:22 -060024namespace responder
25{
Sampa Misra032bd502019-03-06 05:03:22 -060026namespace utils
27{
Sampa Misra032bd502019-03-06 05:03:22 -060028void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
29 uint8_t& hours, uint8_t& day, uint8_t& month,
30 uint16_t& year)
31{
32 auto t = time_t(timeSec);
33 auto time = localtime(&t);
34
George Liu83409572019-12-24 18:42:54 +080035 seconds = pldm::utils::decimalToBcd(time->tm_sec);
36 minutes = pldm::utils::decimalToBcd(time->tm_min);
37 hours = pldm::utils::decimalToBcd(time->tm_hour);
38 day = pldm::utils::decimalToBcd(time->tm_mday);
39 month = pldm::utils::decimalToBcd(time->tm_mon +
40 1); // The number of months in the range
41 // 0 to 11.PLDM expects range 1 to 12
42 year = pldm::utils::decimalToBcd(time->tm_year +
43 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060044}
45
Xiaochao Ma60227a02019-12-04 09:00:12 +080046std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
47 uint8_t day, uint8_t month, uint16_t year)
48{
49 struct std::tm stm;
50
51 stm.tm_year = year - 1900;
52 stm.tm_mon = month - 1;
53 stm.tm_mday = day;
54 stm.tm_hour = hours;
55 stm.tm_min = minutes;
56 stm.tm_sec = seconds;
57 stm.tm_isdst = -1;
58
59 // It will get the time in seconds since
60 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
61 return timegm(&stm);
62}
63
Sampa Misra032bd502019-03-06 05:03:22 -060064} // namespace utils
65
Deepak Kodihallibc669f12019-11-28 08:52:07 -060066namespace bios
67{
John Wang6080aae2020-02-14 09:34:25 +080068using EpochTimeUS = uint64_t;
69
70DBusHandler dbusHandler;
71
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060072Handler::Handler(
73 int fd, uint8_t eid, pldm::InstanceIdDb* instanceIdDb,
74 pldm::requester::Handler<pldm::requester::Request>* handler,
75 pldm::responder::platform_config::Handler* platformConfigHandler) :
Tom Joseph7f839f92020-09-21 10:20:44 +053076 biosConfig(BIOS_JSONS_DIR, BIOS_TABLES_DIR, &dbusHandler, fd, eid,
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060077 instanceIdDb, handler, platformConfigHandler)
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060078{
John Wang6080aae2020-02-14 09:34:25 +080079 biosConfig.removeTables();
80 biosConfig.buildTables();
81
Delphine CC Chiud2e48992023-12-05 16:29:51 +080082 handlers.emplace(
83 PLDM_SET_DATE_TIME,
84 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
Patrick Williams6da4f912023-05-10 07:50:53 -050085 return this->setDateTime(request, payloadLength);
86 });
Delphine CC Chiud2e48992023-12-05 16:29:51 +080087 handlers.emplace(
88 PLDM_GET_DATE_TIME,
89 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
Patrick Williams6da4f912023-05-10 07:50:53 -050090 return this->getDateTime(request, payloadLength);
91 });
Delphine CC Chiud2e48992023-12-05 16:29:51 +080092 handlers.emplace(
93 PLDM_GET_BIOS_TABLE,
94 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
Patrick Williams6da4f912023-05-10 07:50:53 -050095 return this->getBIOSTable(request, payloadLength);
96 });
Delphine CC Chiud2e48992023-12-05 16:29:51 +080097 handlers.emplace(
98 PLDM_SET_BIOS_TABLE,
99 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500100 return this->setBIOSTable(request, payloadLength);
101 });
Delphine CC Chiud2e48992023-12-05 16:29:51 +0800102 handlers.emplace(
103 PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
104 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500105 return this->getBIOSAttributeCurrentValueByHandle(request,
106 payloadLength);
107 });
Delphine CC Chiud2e48992023-12-05 16:29:51 +0800108 handlers.emplace(
109 PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
110 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500111 return this->setBIOSAttributeCurrentValue(request, payloadLength);
112 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600113}
114
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600115Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600116{
117 uint8_t seconds = 0;
118 uint8_t minutes = 0;
119 uint8_t hours = 0;
120 uint8_t day = 0;
121 uint8_t month = 0;
122 uint16_t year = 0;
123
124 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800125 constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
vkaverapa6575b82019-04-03 05:33:52 -0500126 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
127 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800128 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600129
Sampa Misra032bd502019-03-06 05:03:22 -0600130 try
131 {
George Liu782d37f2020-01-24 09:02:17 +0800132 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
George Liufd972642020-04-12 12:08:23 +0800133 bmcTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600134 }
Patrick Williams84b790c2022-07-22 19:26:56 -0500135 catch (const sdbusplus::exception_t& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600136 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600137 error(
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500138 "Error getting time from Elapsed property at '{PATH}' on '{INTERFACE}': {ERROR}",
139 "PATH", bmcTimePath, "INTERFACE", timeInterface, "ERROR", e);
George Liufb8611d2019-12-06 10:14:15 +0800140 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600141 }
142
Sampa Misra032bd502019-03-06 05:03:22 -0600143 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
144 std::chrono::microseconds(timeUsec))
145 .count();
146
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600147 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
148 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600149
George Liufb8611d2019-12-06 10:14:15 +0800150 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
151 seconds, minutes, hours, day, month,
152 year, responsePtr);
153 if (rc != PLDM_SUCCESS)
154 {
155 return ccOnlyResponse(request, rc);
156 }
157
vkaverapa6575b82019-04-03 05:33:52 -0500158 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600159}
160
Xiaochao Ma60227a02019-12-04 09:00:12 +0800161Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
162{
163 uint8_t seconds = 0;
164 uint8_t minutes = 0;
165 uint8_t hours = 0;
166 uint8_t day = 0;
167 uint8_t month = 0;
168 uint16_t year = 0;
169 std::time_t timeSec;
170
Pavithra Barithaya297720a2022-09-12 05:50:38 -0500171 constexpr auto timeSyncPath = "/xyz/openbmc_project/time/sync_method";
172 constexpr auto timeSyncInterface =
173 "xyz.openbmc_project.Time.Synchronization";
174 constexpr auto timeSyncProperty = "TimeSyncMethod";
175
176 // The time is correct on BMC when in NTP mode, so we do not want to
177 // try and set the time again and cause potential time drifts.
178 try
179 {
180 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant(
181 timeSyncPath, timeSyncProperty, timeSyncInterface);
182 const auto& mode = std::get<std::string>(propVal);
183
184 if (mode == "xyz.openbmc_project.Time.Synchronization.Method.NTP")
185 {
186 return ccOnlyResponse(request, PLDM_SUCCESS);
187 }
188 }
189 catch (const std::exception& e)
190 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600191 error(
192 "Error getting the time sync property, PATH={TIME_SYNC_PATH} INTERFACE={SYNC_INTERFACE} PROPERTY={SYNC_PROP} ERROR={ERR_EXCEP}",
193 "TIME_SYNC_PATH", timeSyncPath, "SYNC_INTERFACE", timeSyncInterface,
194 "SYNC_PROP", timeSyncProperty, "ERR_EXCEP", e.what());
Pavithra Barithaya297720a2022-09-12 05:50:38 -0500195 }
196
Xiaochao Ma60227a02019-12-04 09:00:12 +0800197 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800198 constexpr auto setTimePath = "/xyz/openbmc_project/time/bmc";
Xiaochao Ma60227a02019-12-04 09:00:12 +0800199 constexpr auto timeSetPro = "Elapsed";
200
201 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
202 &minutes, &hours, &day, &month, &year);
203 if (rc != PLDM_SUCCESS)
204 {
205 return ccOnlyResponse(request, rc);
206 }
207 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
208 month, year);
209 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
210 std::chrono::seconds(timeSec))
211 .count();
George Liu1e44c732020-02-28 20:20:06 +0800212 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800213 try
214 {
George Liu1e44c732020-02-28 20:20:06 +0800215 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
216 "uint64_t"};
217 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800218 }
Patrick Williams51330582021-10-06 12:48:56 -0500219 catch (const std::exception& e)
Xiaochao Ma60227a02019-12-04 09:00:12 +0800220 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600221 error(
222 "Error Setting time,PATH={SET_TIME_PATH} TIME INTERFACE={TIME_INTERFACE} ERROR={ERR_EXCEP}",
223 "SET_TIME_PATH", setTimePath, "TIME_INTERFACE", setTimeInterface,
224 "ERR_EXCEP", e.what());
Xiaochao Ma60227a02019-12-04 09:00:12 +0800225 return ccOnlyResponse(request, PLDM_ERROR);
226 }
227
228 return ccOnlyResponse(request, PLDM_SUCCESS);
229}
230
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600231Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500232{
John Wang6080aae2020-02-14 09:34:25 +0800233 uint32_t transferHandle{};
234 uint8_t transferOpFlag{};
235 uint8_t tableType{};
236
237 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
238 &transferOpFlag, &tableType);
239 if (rc != PLDM_SUCCESS)
240 {
241 return ccOnlyResponse(request, rc);
242 }
243
244 auto table =
245 biosConfig.getBIOSTable(static_cast<pldm_bios_table_types>(tableType));
246 if (!table)
247 {
248 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
249 }
250
251 Response response(sizeof(pldm_msg_hdr) +
252 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + table->size());
253 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
254
255 rc = encode_get_bios_table_resp(
256 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
257 PLDM_START_AND_END, table->data(), response.size(), responsePtr);
258 if (rc != PLDM_SUCCESS)
259 {
260 return ccOnlyResponse(request, rc);
261 }
Sampa Misrab37be312019-07-03 02:26:41 -0500262
263 return response;
264}
265
George Liu1b180d82020-07-23 14:01:58 +0800266Response Handler::setBIOSTable(const pldm_msg* request, size_t payloadLength)
267{
268 uint32_t transferHandle{};
269 uint8_t transferOpFlag{};
270 uint8_t tableType{};
271 struct variable_field field;
272
273 auto rc = decode_set_bios_table_req(request, payloadLength, &transferHandle,
274 &transferOpFlag, &tableType, &field);
275 if (rc != PLDM_SUCCESS)
276 {
277 return ccOnlyResponse(request, rc);
278 }
279
280 Table table(field.ptr, field.ptr + field.length);
281 rc = biosConfig.setBIOSTable(tableType, table);
282 if (rc != PLDM_SUCCESS)
283 {
284 return ccOnlyResponse(request, rc);
285 }
286
287 Response response(sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_TABLE_RESP_BYTES);
288 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
289
290 rc = encode_set_bios_table_resp(request->hdr.instance_id, PLDM_SUCCESS,
291 0 /* nxtTransferHandle */, responsePtr);
292 if (rc != PLDM_SUCCESS)
293 {
294 return ccOnlyResponse(request, rc);
295 }
296
297 return response;
298}
299
John Wang8721ed62019-12-05 14:44:43 +0800300Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
301 size_t payloadLength)
302{
303 uint32_t transferHandle;
304 uint8_t transferOpFlag;
305 uint16_t attributeHandle;
306
307 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
308 request, payloadLength, &transferHandle, &transferOpFlag,
309 &attributeHandle);
310 if (rc != PLDM_SUCCESS)
311 {
312 return ccOnlyResponse(request, rc);
313 }
314
John Wang6080aae2020-02-14 09:34:25 +0800315 auto table = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
316 if (!table)
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600317 {
318 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
319 }
320
John Wang8721ed62019-12-05 14:44:43 +0800321 auto entry = pldm_bios_table_attr_value_find_by_handle(
John Wang6080aae2020-02-14 09:34:25 +0800322 table->data(), table->size(), attributeHandle);
John Wang8721ed62019-12-05 14:44:43 +0800323 if (entry == nullptr)
324 {
325 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
326 }
327
John Wang8e877e02020-02-03 16:06:55 +0800328 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800329 Response response(sizeof(pldm_msg_hdr) +
330 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800331 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800332 0);
333 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800334 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800335 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
336 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800337 if (rc != PLDM_SUCCESS)
338 {
339 return ccOnlyResponse(request, rc);
340 }
John Wang8721ed62019-12-05 14:44:43 +0800341
342 return response;
343}
344
John Wang42174882019-12-20 14:56:59 +0800345Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
346 size_t payloadLength)
347{
348 uint32_t transferHandle;
349 uint8_t transferOpFlag;
350 variable_field attributeField;
351
352 auto rc = decode_set_bios_attribute_current_value_req(
353 request, payloadLength, &transferHandle, &transferOpFlag,
354 &attributeField);
355 if (rc != PLDM_SUCCESS)
356 {
357 return ccOnlyResponse(request, rc);
358 }
359
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600360 rc = biosConfig.setAttrValue(attributeField.ptr, attributeField.length,
361 false);
John Wang42174882019-12-20 14:56:59 +0800362
Xiaochao Ma7a0d0722020-05-29 09:07:33 +0800363 Response response(
364 sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES, 0);
365 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
366
367 encode_set_bios_attribute_current_value_resp(request->hdr.instance_id, rc,
368 0, responsePtr);
369
370 return response;
John Wang42174882019-12-20 14:56:59 +0800371}
372
John Wangf719f3b2020-01-17 08:46:22 +0800373} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -0600374} // namespace responder
375} // namespace pldm