blob: 2306ad9898878bc168dea3e21f31e4b07cf7f6ef [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{
20
Sampa Misra032bd502019-03-06 05:03:22 -060021namespace responder
22{
23
24namespace utils
25{
26
27void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
28 uint8_t& hours, uint8_t& day, uint8_t& month,
29 uint16_t& year)
30{
31 auto t = time_t(timeSec);
32 auto time = localtime(&t);
33
George Liu83409572019-12-24 18:42:54 +080034 seconds = pldm::utils::decimalToBcd(time->tm_sec);
35 minutes = pldm::utils::decimalToBcd(time->tm_min);
36 hours = pldm::utils::decimalToBcd(time->tm_hour);
37 day = pldm::utils::decimalToBcd(time->tm_mday);
38 month = pldm::utils::decimalToBcd(time->tm_mon +
39 1); // The number of months in the range
40 // 0 to 11.PLDM expects range 1 to 12
41 year = pldm::utils::decimalToBcd(time->tm_year +
42 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060043}
44
Xiaochao Ma60227a02019-12-04 09:00:12 +080045std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
46 uint8_t day, uint8_t month, uint16_t year)
47{
48 struct std::tm stm;
49
50 stm.tm_year = year - 1900;
51 stm.tm_mon = month - 1;
52 stm.tm_mday = day;
53 stm.tm_hour = hours;
54 stm.tm_min = minutes;
55 stm.tm_sec = seconds;
56 stm.tm_isdst = -1;
57
58 // It will get the time in seconds since
59 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
60 return timegm(&stm);
61}
62
Sampa Misra032bd502019-03-06 05:03:22 -060063} // namespace utils
64
Deepak Kodihallibc669f12019-11-28 08:52:07 -060065namespace bios
66{
67
John Wang6080aae2020-02-14 09:34:25 +080068using EpochTimeUS = uint64_t;
69
70DBusHandler dbusHandler;
71
Sampa Misrac0c79482021-06-02 08:01:54 -050072Handler::Handler(int fd, uint8_t eid, dbus_api::Requester* requester,
73 pldm::requester::Handler<pldm::requester::Request>* handler) :
Tom Joseph7f839f92020-09-21 10:20:44 +053074 biosConfig(BIOS_JSONS_DIR, BIOS_TABLES_DIR, &dbusHandler, fd, eid,
Sampa Misrac0c79482021-06-02 08:01:54 -050075 requester, handler)
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060076{
John Wang6080aae2020-02-14 09:34:25 +080077 biosConfig.removeTables();
78 biosConfig.buildTables();
79
Xiaochao Ma60227a02019-12-04 09:00:12 +080080 handlers.emplace(PLDM_SET_DATE_TIME,
81 [this](const pldm_msg* request, size_t payloadLength) {
82 return this->setDateTime(request, payloadLength);
83 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060084 handlers.emplace(PLDM_GET_DATE_TIME,
85 [this](const pldm_msg* request, size_t payloadLength) {
86 return this->getDateTime(request, payloadLength);
87 });
88 handlers.emplace(PLDM_GET_BIOS_TABLE,
89 [this](const pldm_msg* request, size_t payloadLength) {
90 return this->getBIOSTable(request, payloadLength);
91 });
George Liu1b180d82020-07-23 14:01:58 +080092 handlers.emplace(PLDM_SET_BIOS_TABLE,
93 [this](const pldm_msg* request, size_t payloadLength) {
94 return this->setBIOSTable(request, payloadLength);
95 });
John Wang8721ed62019-12-05 14:44:43 +080096 handlers.emplace(PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
97 [this](const pldm_msg* request, size_t payloadLength) {
98 return this->getBIOSAttributeCurrentValueByHandle(
99 request, payloadLength);
100 });
John Wang42174882019-12-20 14:56:59 +0800101 handlers.emplace(PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
102 [this](const pldm_msg* request, size_t payloadLength) {
103 return this->setBIOSAttributeCurrentValue(
104 request, payloadLength);
105 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600106}
107
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600108Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600109{
110 uint8_t seconds = 0;
111 uint8_t minutes = 0;
112 uint8_t hours = 0;
113 uint8_t day = 0;
114 uint8_t month = 0;
115 uint16_t year = 0;
116
117 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800118 constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
vkaverapa6575b82019-04-03 05:33:52 -0500119 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
120 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800121 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600122
Sampa Misra032bd502019-03-06 05:03:22 -0600123 try
124 {
George Liu782d37f2020-01-24 09:02:17 +0800125 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
George Liufd972642020-04-12 12:08:23 +0800126 bmcTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600127 }
Patrick Williams84b790c2022-07-22 19:26:56 -0500128 catch (const sdbusplus::exception_t& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600129 {
George Liufd972642020-04-12 12:08:23 +0800130 std::cerr << "Error getting time, PATH=" << bmcTimePath
Sampa Misraaa8ae722019-12-12 03:20:40 -0600131 << " TIME INTERACE=" << timeInterface << "\n";
Sampa Misra032bd502019-03-06 05:03:22 -0600132
George Liufb8611d2019-12-06 10:14:15 +0800133 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600134 }
135
Sampa Misra032bd502019-03-06 05:03:22 -0600136 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
137 std::chrono::microseconds(timeUsec))
138 .count();
139
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600140 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
141 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600142
George Liufb8611d2019-12-06 10:14:15 +0800143 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
144 seconds, minutes, hours, day, month,
145 year, responsePtr);
146 if (rc != PLDM_SUCCESS)
147 {
148 return ccOnlyResponse(request, rc);
149 }
150
vkaverapa6575b82019-04-03 05:33:52 -0500151 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600152}
153
Xiaochao Ma60227a02019-12-04 09:00:12 +0800154Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
155{
156 uint8_t seconds = 0;
157 uint8_t minutes = 0;
158 uint8_t hours = 0;
159 uint8_t day = 0;
160 uint8_t month = 0;
161 uint16_t year = 0;
162 std::time_t timeSec;
163
164 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liufd972642020-04-12 12:08:23 +0800165 constexpr auto setTimePath = "/xyz/openbmc_project/time/bmc";
Xiaochao Ma60227a02019-12-04 09:00:12 +0800166 constexpr auto timeSetPro = "Elapsed";
167
168 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
169 &minutes, &hours, &day, &month, &year);
170 if (rc != PLDM_SUCCESS)
171 {
172 return ccOnlyResponse(request, rc);
173 }
174 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
175 month, year);
176 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
177 std::chrono::seconds(timeSec))
178 .count();
George Liu1e44c732020-02-28 20:20:06 +0800179 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800180 try
181 {
George Liu1e44c732020-02-28 20:20:06 +0800182 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
183 "uint64_t"};
184 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800185 }
Patrick Williams51330582021-10-06 12:48:56 -0500186 catch (const std::exception& e)
Xiaochao Ma60227a02019-12-04 09:00:12 +0800187 {
Xiaochao Ma60227a02019-12-04 09:00:12 +0800188 std::cerr << "Error Setting time,PATH=" << setTimePath
189 << "TIME INTERFACE=" << setTimeInterface
190 << "ERROR=" << e.what() << "\n";
191
192 return ccOnlyResponse(request, PLDM_ERROR);
193 }
194
195 return ccOnlyResponse(request, PLDM_SUCCESS);
196}
197
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600198Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500199{
John Wang6080aae2020-02-14 09:34:25 +0800200 uint32_t transferHandle{};
201 uint8_t transferOpFlag{};
202 uint8_t tableType{};
203
204 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
205 &transferOpFlag, &tableType);
206 if (rc != PLDM_SUCCESS)
207 {
208 return ccOnlyResponse(request, rc);
209 }
210
211 auto table =
212 biosConfig.getBIOSTable(static_cast<pldm_bios_table_types>(tableType));
213 if (!table)
214 {
215 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
216 }
217
218 Response response(sizeof(pldm_msg_hdr) +
219 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + table->size());
220 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
221
222 rc = encode_get_bios_table_resp(
223 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
224 PLDM_START_AND_END, table->data(), response.size(), responsePtr);
225 if (rc != PLDM_SUCCESS)
226 {
227 return ccOnlyResponse(request, rc);
228 }
Sampa Misrab37be312019-07-03 02:26:41 -0500229
230 return response;
231}
232
George Liu1b180d82020-07-23 14:01:58 +0800233Response Handler::setBIOSTable(const pldm_msg* request, size_t payloadLength)
234{
235 uint32_t transferHandle{};
236 uint8_t transferOpFlag{};
237 uint8_t tableType{};
238 struct variable_field field;
239
240 auto rc = decode_set_bios_table_req(request, payloadLength, &transferHandle,
241 &transferOpFlag, &tableType, &field);
242 if (rc != PLDM_SUCCESS)
243 {
244 return ccOnlyResponse(request, rc);
245 }
246
247 Table table(field.ptr, field.ptr + field.length);
248 rc = biosConfig.setBIOSTable(tableType, table);
249 if (rc != PLDM_SUCCESS)
250 {
251 return ccOnlyResponse(request, rc);
252 }
253
254 Response response(sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_TABLE_RESP_BYTES);
255 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
256
257 rc = encode_set_bios_table_resp(request->hdr.instance_id, PLDM_SUCCESS,
258 0 /* nxtTransferHandle */, responsePtr);
259 if (rc != PLDM_SUCCESS)
260 {
261 return ccOnlyResponse(request, rc);
262 }
263
264 return response;
265}
266
John Wang8721ed62019-12-05 14:44:43 +0800267Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
268 size_t payloadLength)
269{
270 uint32_t transferHandle;
271 uint8_t transferOpFlag;
272 uint16_t attributeHandle;
273
274 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
275 request, payloadLength, &transferHandle, &transferOpFlag,
276 &attributeHandle);
277 if (rc != PLDM_SUCCESS)
278 {
279 return ccOnlyResponse(request, rc);
280 }
281
John Wang6080aae2020-02-14 09:34:25 +0800282 auto table = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
283 if (!table)
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600284 {
285 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
286 }
287
John Wang8721ed62019-12-05 14:44:43 +0800288 auto entry = pldm_bios_table_attr_value_find_by_handle(
John Wang6080aae2020-02-14 09:34:25 +0800289 table->data(), table->size(), attributeHandle);
John Wang8721ed62019-12-05 14:44:43 +0800290 if (entry == nullptr)
291 {
292 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
293 }
294
John Wang8e877e02020-02-03 16:06:55 +0800295 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800296 Response response(sizeof(pldm_msg_hdr) +
297 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800298 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800299 0);
300 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800301 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800302 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
303 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800304 if (rc != PLDM_SUCCESS)
305 {
306 return ccOnlyResponse(request, rc);
307 }
John Wang8721ed62019-12-05 14:44:43 +0800308
309 return response;
310}
311
John Wang42174882019-12-20 14:56:59 +0800312Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
313 size_t payloadLength)
314{
315 uint32_t transferHandle;
316 uint8_t transferOpFlag;
317 variable_field attributeField;
318
319 auto rc = decode_set_bios_attribute_current_value_req(
320 request, payloadLength, &transferHandle, &transferOpFlag,
321 &attributeField);
322 if (rc != PLDM_SUCCESS)
323 {
324 return ccOnlyResponse(request, rc);
325 }
326
John Wang6080aae2020-02-14 09:34:25 +0800327 rc = biosConfig.setAttrValue(attributeField.ptr, attributeField.length);
John Wang42174882019-12-20 14:56:59 +0800328
Xiaochao Ma7a0d0722020-05-29 09:07:33 +0800329 Response response(
330 sizeof(pldm_msg_hdr) + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES, 0);
331 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
332
333 encode_set_bios_attribute_current_value_resp(request->hdr.instance_id, rc,
334 0, responsePtr);
335
336 return response;
John Wang42174882019-12-20 14:56:59 +0800337}
338
John Wangf719f3b2020-01-17 08:46:22 +0800339} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -0600340} // namespace responder
341} // namespace pldm