blob: 93e8302775ac6ea32bb62adbc9b77c3ac820e981 [file] [log] [blame]
Sampa Misra032bd502019-03-06 05:03:22 -06001#include "bios.hpp"
2
George Liu83409572019-12-24 18:42:54 +08003#include "utils.hpp"
Sampa Misra032bd502019-03-06 05:03:22 -06004#include "xyz/openbmc_project/Common/error.hpp"
5
Xiaochao Ma60227a02019-12-04 09:00:12 +08006#include <time.h>
7
Sampa Misra032bd502019-03-06 05:03:22 -06008#include <array>
Sampa Misrab37be312019-07-03 02:26:41 -05009#include <boost/crc.hpp>
Sampa Misra032bd502019-03-06 05:03:22 -060010#include <chrono>
11#include <ctime>
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060012#include <filesystem>
Sampa Misraaa8ae722019-12-12 03:20:40 -060013#include <iostream>
John Wang02700402019-10-06 16:34:29 +080014#include <memory>
Sampa Misrab37be312019-07-03 02:26:41 -050015#include <numeric>
Sampa Misra032bd502019-03-06 05:03:22 -060016#include <stdexcept>
17#include <string>
18#include <variant>
19#include <vector>
20
21namespace pldm
22{
23
Sampa Misra032bd502019-03-06 05:03:22 -060024namespace responder
25{
26
27namespace utils
28{
29
30void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
31 uint8_t& hours, uint8_t& day, uint8_t& month,
32 uint16_t& year)
33{
34 auto t = time_t(timeSec);
35 auto time = localtime(&t);
36
George Liu83409572019-12-24 18:42:54 +080037 seconds = pldm::utils::decimalToBcd(time->tm_sec);
38 minutes = pldm::utils::decimalToBcd(time->tm_min);
39 hours = pldm::utils::decimalToBcd(time->tm_hour);
40 day = pldm::utils::decimalToBcd(time->tm_mday);
41 month = pldm::utils::decimalToBcd(time->tm_mon +
42 1); // The number of months in the range
43 // 0 to 11.PLDM expects range 1 to 12
44 year = pldm::utils::decimalToBcd(time->tm_year +
45 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060046}
47
Xiaochao Ma60227a02019-12-04 09:00:12 +080048std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
49 uint8_t day, uint8_t month, uint16_t year)
50{
51 struct std::tm stm;
52
53 stm.tm_year = year - 1900;
54 stm.tm_mon = month - 1;
55 stm.tm_mday = day;
56 stm.tm_hour = hours;
57 stm.tm_min = minutes;
58 stm.tm_sec = seconds;
59 stm.tm_isdst = -1;
60
61 // It will get the time in seconds since
62 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
63 return timegm(&stm);
64}
65
Sampa Misra032bd502019-03-06 05:03:22 -060066} // namespace utils
67
Deepak Kodihallibc669f12019-11-28 08:52:07 -060068namespace bios
69{
70
John Wang6080aae2020-02-14 09:34:25 +080071using EpochTimeUS = uint64_t;
72
73DBusHandler dbusHandler;
74
75Handler::Handler() : biosConfig(BIOS_JSONS_DIR, BIOS_TABLES_DIR, &dbusHandler)
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 });
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 Liu408c3c42019-10-16 16:49:15 +0800114 constexpr auto hostTimePath = "/xyz/openbmc_project/time/host";
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>(
122 hostTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600123 }
George Liu0e02c322020-01-01 09:41:51 +0800124 catch (const sdbusplus::exception::SdBusError& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600125 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600126 std::cerr << "Error getting time, PATH=" << hostTimePath
127 << " 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
160 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
161 constexpr auto setTimePath = "/xyz/openbmc_project/time/host";
162 constexpr auto timeSetPro = "Elapsed";
163
164 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
165 &minutes, &hours, &day, &month, &year);
166 if (rc != PLDM_SUCCESS)
167 {
168 return ccOnlyResponse(request, rc);
169 }
170 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
171 month, year);
172 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
173 std::chrono::seconds(timeSec))
174 .count();
George Liu1e44c732020-02-28 20:20:06 +0800175 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800176 try
177 {
George Liu1e44c732020-02-28 20:20:06 +0800178 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
179 "uint64_t"};
180 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800181 }
182 catch (std::exception& e)
183 {
184
185 std::cerr << "Error Setting time,PATH=" << setTimePath
186 << "TIME INTERFACE=" << setTimeInterface
187 << "ERROR=" << e.what() << "\n";
188
189 return ccOnlyResponse(request, PLDM_ERROR);
190 }
191
192 return ccOnlyResponse(request, PLDM_SUCCESS);
193}
194
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600195Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500196{
John Wang6080aae2020-02-14 09:34:25 +0800197 uint32_t transferHandle{};
198 uint8_t transferOpFlag{};
199 uint8_t tableType{};
200
201 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
202 &transferOpFlag, &tableType);
203 if (rc != PLDM_SUCCESS)
204 {
205 return ccOnlyResponse(request, rc);
206 }
207
208 auto table =
209 biosConfig.getBIOSTable(static_cast<pldm_bios_table_types>(tableType));
210 if (!table)
211 {
212 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
213 }
214
215 Response response(sizeof(pldm_msg_hdr) +
216 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + table->size());
217 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
218
219 rc = encode_get_bios_table_resp(
220 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
221 PLDM_START_AND_END, table->data(), response.size(), responsePtr);
222 if (rc != PLDM_SUCCESS)
223 {
224 return ccOnlyResponse(request, rc);
225 }
Sampa Misrab37be312019-07-03 02:26:41 -0500226
227 return response;
228}
229
John Wang8721ed62019-12-05 14:44:43 +0800230Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
231 size_t payloadLength)
232{
233 uint32_t transferHandle;
234 uint8_t transferOpFlag;
235 uint16_t attributeHandle;
236
237 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
238 request, payloadLength, &transferHandle, &transferOpFlag,
239 &attributeHandle);
240 if (rc != PLDM_SUCCESS)
241 {
242 return ccOnlyResponse(request, rc);
243 }
244
John Wang6080aae2020-02-14 09:34:25 +0800245 auto table = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
246 if (!table)
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600247 {
248 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
249 }
250
John Wang8721ed62019-12-05 14:44:43 +0800251 auto entry = pldm_bios_table_attr_value_find_by_handle(
John Wang6080aae2020-02-14 09:34:25 +0800252 table->data(), table->size(), attributeHandle);
John Wang8721ed62019-12-05 14:44:43 +0800253 if (entry == nullptr)
254 {
255 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
256 }
257
John Wang8e877e02020-02-03 16:06:55 +0800258 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800259 Response response(sizeof(pldm_msg_hdr) +
260 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800261 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800262 0);
263 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800264 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800265 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
266 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800267 if (rc != PLDM_SUCCESS)
268 {
269 return ccOnlyResponse(request, rc);
270 }
John Wang8721ed62019-12-05 14:44:43 +0800271
272 return response;
273}
274
John Wang42174882019-12-20 14:56:59 +0800275Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
276 size_t payloadLength)
277{
278 uint32_t transferHandle;
279 uint8_t transferOpFlag;
280 variable_field attributeField;
281
282 auto rc = decode_set_bios_attribute_current_value_req(
283 request, payloadLength, &transferHandle, &transferOpFlag,
284 &attributeField);
285 if (rc != PLDM_SUCCESS)
286 {
287 return ccOnlyResponse(request, rc);
288 }
289
John Wang6080aae2020-02-14 09:34:25 +0800290 rc = biosConfig.setAttrValue(attributeField.ptr, attributeField.length);
John Wang42174882019-12-20 14:56:59 +0800291
John Wang6080aae2020-02-14 09:34:25 +0800292 return ccOnlyResponse(request, rc);
John Wang42174882019-12-20 14:56:59 +0800293}
294
John Wangf719f3b2020-01-17 08:46:22 +0800295} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -0600296} // namespace responder
297} // namespace pldm