blob: fe201405a34ee2e560577aedd0dbcf5d2c387fb4 [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
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060021namespace fs = std::filesystem;
Sampa Misrab37be312019-07-03 02:26:41 -050022using namespace pldm::responder::bios;
23using namespace bios_parser;
Sampa Misrab37be312019-07-03 02:26:41 -050024
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060025constexpr auto stringTableFile = "stringTable";
26constexpr auto attrTableFile = "attributeTable";
27constexpr auto attrValTableFile = "attributeValueTable";
28
Sampa Misra032bd502019-03-06 05:03:22 -060029namespace pldm
30{
31
Sampa Misrab37be312019-07-03 02:26:41 -050032using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Sampa Misra032bd502019-03-06 05:03:22 -060033using EpochTimeUS = uint64_t;
Sampa Misrab37be312019-07-03 02:26:41 -050034using BIOSTableRow = std::vector<uint8_t>;
Carol Wangdc220c82019-08-26 13:31:31 +080035using BIOSJsonName = std::string;
Sampa Misra032bd502019-03-06 05:03:22 -060036
37constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
Sampa Misrab37be312019-07-03 02:26:41 -050038constexpr auto padChksumMax = 7;
Sampa Misra032bd502019-03-06 05:03:22 -060039
40namespace responder
41{
42
43namespace utils
44{
45
46void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
47 uint8_t& hours, uint8_t& day, uint8_t& month,
48 uint16_t& year)
49{
50 auto t = time_t(timeSec);
51 auto time = localtime(&t);
52
George Liu83409572019-12-24 18:42:54 +080053 seconds = pldm::utils::decimalToBcd(time->tm_sec);
54 minutes = pldm::utils::decimalToBcd(time->tm_min);
55 hours = pldm::utils::decimalToBcd(time->tm_hour);
56 day = pldm::utils::decimalToBcd(time->tm_mday);
57 month = pldm::utils::decimalToBcd(time->tm_mon +
58 1); // The number of months in the range
59 // 0 to 11.PLDM expects range 1 to 12
60 year = pldm::utils::decimalToBcd(time->tm_year +
61 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060062}
63
Xiaochao Ma60227a02019-12-04 09:00:12 +080064std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
65 uint8_t day, uint8_t month, uint16_t year)
66{
67 struct std::tm stm;
68
69 stm.tm_year = year - 1900;
70 stm.tm_mon = month - 1;
71 stm.tm_mday = day;
72 stm.tm_hour = hours;
73 stm.tm_min = minutes;
74 stm.tm_sec = seconds;
75 stm.tm_isdst = -1;
76
77 // It will get the time in seconds since
78 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
79 return timegm(&stm);
80}
81
John Wangc2938352019-09-30 13:58:41 +080082size_t getTableTotalsize(size_t sizeWithoutPad)
83{
John Wang79c37f12019-10-31 15:46:31 +080084 return sizeWithoutPad + pldm_bios_table_pad_checksum_size(sizeWithoutPad);
John Wangc2938352019-09-30 13:58:41 +080085}
86
87void padAndChecksum(Table& table)
88{
John Wang79c37f12019-10-31 15:46:31 +080089 auto sizeWithoutPad = table.size();
90 auto padAndChecksumSize = pldm_bios_table_pad_checksum_size(sizeWithoutPad);
91 table.resize(table.size() + padAndChecksumSize);
John Wangc2938352019-09-30 13:58:41 +080092
John Wang79c37f12019-10-31 15:46:31 +080093 pldm_bios_table_append_pad_checksum(table.data(), table.size(),
94 sizeWithoutPad);
John Wangc2938352019-09-30 13:58:41 +080095}
96
Sampa Misra032bd502019-03-06 05:03:22 -060097} // namespace utils
98
Deepak Kodihallibc669f12019-11-28 08:52:07 -060099namespace bios
100{
101
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600102Handler::Handler()
103{
104 try
105 {
106 fs::remove(
107 fs::path(std::string(BIOS_TABLES_DIR) + "/" + stringTableFile));
108 fs::remove(
109 fs::path(std::string(BIOS_TABLES_DIR) + "/" + attrTableFile));
110 fs::remove(
111 fs::path(std::string(BIOS_TABLES_DIR) + "/" + attrValTableFile));
112 }
113 catch (const std::exception& e)
114 {
115 }
Xiaochao Ma60227a02019-12-04 09:00:12 +0800116 handlers.emplace(PLDM_SET_DATE_TIME,
117 [this](const pldm_msg* request, size_t payloadLength) {
118 return this->setDateTime(request, payloadLength);
119 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600120 handlers.emplace(PLDM_GET_DATE_TIME,
121 [this](const pldm_msg* request, size_t payloadLength) {
122 return this->getDateTime(request, payloadLength);
123 });
124 handlers.emplace(PLDM_GET_BIOS_TABLE,
125 [this](const pldm_msg* request, size_t payloadLength) {
126 return this->getBIOSTable(request, payloadLength);
127 });
John Wang8721ed62019-12-05 14:44:43 +0800128 handlers.emplace(PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
129 [this](const pldm_msg* request, size_t payloadLength) {
130 return this->getBIOSAttributeCurrentValueByHandle(
131 request, payloadLength);
132 });
John Wang42174882019-12-20 14:56:59 +0800133 handlers.emplace(PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
134 [this](const pldm_msg* request, size_t payloadLength) {
135 return this->setBIOSAttributeCurrentValue(
136 request, payloadLength);
137 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600138}
139
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600140Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600141{
142 uint8_t seconds = 0;
143 uint8_t minutes = 0;
144 uint8_t hours = 0;
145 uint8_t day = 0;
146 uint8_t month = 0;
147 uint16_t year = 0;
148
149 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liu408c3c42019-10-16 16:49:15 +0800150 constexpr auto hostTimePath = "/xyz/openbmc_project/time/host";
vkaverapa6575b82019-04-03 05:33:52 -0500151 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
152 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800153 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600154
Sampa Misra032bd502019-03-06 05:03:22 -0600155 try
156 {
George Liu782d37f2020-01-24 09:02:17 +0800157 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
158 hostTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600159 }
George Liu0e02c322020-01-01 09:41:51 +0800160 catch (const sdbusplus::exception::SdBusError& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600161 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600162 std::cerr << "Error getting time, PATH=" << hostTimePath
163 << " TIME INTERACE=" << timeInterface << "\n";
Sampa Misra032bd502019-03-06 05:03:22 -0600164
George Liufb8611d2019-12-06 10:14:15 +0800165 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600166 }
167
Sampa Misra032bd502019-03-06 05:03:22 -0600168 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
169 std::chrono::microseconds(timeUsec))
170 .count();
171
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600172 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
173 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600174
George Liufb8611d2019-12-06 10:14:15 +0800175 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
176 seconds, minutes, hours, day, month,
177 year, responsePtr);
178 if (rc != PLDM_SUCCESS)
179 {
180 return ccOnlyResponse(request, rc);
181 }
182
vkaverapa6575b82019-04-03 05:33:52 -0500183 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600184}
185
Xiaochao Ma60227a02019-12-04 09:00:12 +0800186Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
187{
188 uint8_t seconds = 0;
189 uint8_t minutes = 0;
190 uint8_t hours = 0;
191 uint8_t day = 0;
192 uint8_t month = 0;
193 uint16_t year = 0;
194 std::time_t timeSec;
195
196 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
197 constexpr auto setTimePath = "/xyz/openbmc_project/time/host";
198 constexpr auto timeSetPro = "Elapsed";
199
200 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
201 &minutes, &hours, &day, &month, &year);
202 if (rc != PLDM_SUCCESS)
203 {
204 return ccOnlyResponse(request, rc);
205 }
206 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
207 month, year);
208 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
209 std::chrono::seconds(timeSec))
210 .count();
211 std::variant<uint64_t> value{timeUsec};
212 try
213 {
214 pldm::utils::DBusHandler().setDbusProperty(setTimePath, timeSetPro,
215 setTimeInterface, value);
216 }
217 catch (std::exception& e)
218 {
219
220 std::cerr << "Error Setting time,PATH=" << setTimePath
221 << "TIME INTERFACE=" << setTimeInterface
222 << "ERROR=" << e.what() << "\n";
223
224 return ccOnlyResponse(request, PLDM_ERROR);
225 }
226
227 return ccOnlyResponse(request, PLDM_SUCCESS);
228}
229
Sampa Misrab37be312019-07-03 02:26:41 -0500230/** @brief Construct the BIOS string table
231 *
John Wangf719f3b2020-01-17 08:46:22 +0800232 * @param[in,out] biosStringTable - the string table
George Liufb8611d2019-12-06 10:14:15 +0800233 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500234 */
John Wangf719f3b2020-01-17 08:46:22 +0800235Response getBIOSStringTable(BIOSTable& biosStringTable, const pldm_msg* request)
John Wange96e7e52019-10-05 17:47:30 +0800236
Sampa Misrab37be312019-07-03 02:26:41 -0500237{
238 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
239 0);
240 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
John Wangf719f3b2020-01-17 08:46:22 +0800241 if (!biosStringTable.isEmpty())
John Wangdd9a6282019-10-11 18:52:46 +0800242 {
George Liufb8611d2019-12-06 10:14:15 +0800243 auto rc = encode_get_bios_table_resp(
244 request->hdr.instance_id, PLDM_SUCCESS,
245 0, /* next transfer handle */
246 PLDM_START_AND_END, nullptr, response.size(),
247 responsePtr); // filling up the header here
248 if (rc != PLDM_SUCCESS)
249 {
250 return CmdHandler::ccOnlyResponse(request, rc);
251 }
252
John Wangf719f3b2020-01-17 08:46:22 +0800253 biosStringTable.load(response);
John Wangdd9a6282019-10-11 18:52:46 +0800254 return response;
255 }
256 auto biosStrings = bios_parser::getStrings();
257 std::sort(biosStrings.begin(), biosStrings.end());
258 // remove all duplicate strings received from bios json
259 biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
260 biosStrings.end());
261
262 size_t sizeWithoutPad = std::accumulate(
263 biosStrings.begin(), biosStrings.end(), 0,
264 [](size_t sum, const std::string& elem) {
265 return sum +
266 pldm_bios_table_string_entry_encode_length(elem.length());
267 });
268
269 Table stringTable;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600270 stringTable.reserve(
271 pldm::responder::utils::getTableTotalsize(sizeWithoutPad));
John Wangdd9a6282019-10-11 18:52:46 +0800272
273 stringTable.resize(sizeWithoutPad);
274 auto tablePtr = stringTable.data();
275 for (const auto& elem : biosStrings)
276 {
277 auto entry_length =
278 pldm_bios_table_string_entry_encode_length(elem.length());
279 pldm_bios_table_string_entry_encode(tablePtr, sizeWithoutPad,
280 elem.c_str(), elem.length());
281 tablePtr += entry_length;
282 sizeWithoutPad -= entry_length;
Sampa Misrab37be312019-07-03 02:26:41 -0500283 }
284
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600285 pldm::responder::utils::padAndChecksum(stringTable);
John Wangf719f3b2020-01-17 08:46:22 +0800286 biosStringTable.store(stringTable);
John Wangdd9a6282019-10-11 18:52:46 +0800287 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
288 stringTable.size(),
289 0);
290 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800291 auto rc = encode_get_bios_table_resp(
292 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
293 PLDM_START_AND_END, stringTable.data(), response.size(), responsePtr);
294 if (rc != PLDM_SUCCESS)
295 {
296 return CmdHandler::ccOnlyResponse(request, rc);
297 }
298
Sampa Misrab37be312019-07-03 02:26:41 -0500299 return response;
300}
301
302/** @brief Find the string handle from the BIOS string table given the name
303 *
304 * @param[in] name - name of the BIOS string
John Wangf719f3b2020-01-17 08:46:22 +0800305 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500306 * @return - uint16_t - handle of the string
307 */
308StringHandle findStringHandle(const std::string& name,
John Wangf719f3b2020-01-17 08:46:22 +0800309 const BIOSTable& biosStringTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500310{
John Wangdd9a6282019-10-11 18:52:46 +0800311 Table table;
John Wangf719f3b2020-01-17 08:46:22 +0800312 biosStringTable.load(table);
John Wangdd9a6282019-10-11 18:52:46 +0800313 auto stringEntry = pldm_bios_table_string_find_by_string(
314 table.data(), table.size(), name.c_str());
315 if (stringEntry == nullptr)
Sampa Misrab37be312019-07-03 02:26:41 -0500316 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600317 std::cerr << "Reached end of BIOS string table,did not find the "
318 << "handle for the string, STRING=" << name.c_str() << "\n";
319 throw InternalFailure();
Sampa Misrab37be312019-07-03 02:26:41 -0500320 }
John Wangdd9a6282019-10-11 18:52:46 +0800321
322 return pldm_bios_table_string_entry_decode_handle(stringEntry);
Sampa Misrab37be312019-07-03 02:26:41 -0500323}
324
325/** @brief Find the string name from the BIOS string table for a string handle
326 *
327 * @param[in] stringHdl - string handle
John Wangf719f3b2020-01-17 08:46:22 +0800328 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500329 *
330 * @return - std::string - name of the corresponding BIOS string
331 */
332std::string findStringName(StringHandle stringHdl,
John Wangf719f3b2020-01-17 08:46:22 +0800333 const BIOSTable& biosStringTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500334{
John Wangdd9a6282019-10-11 18:52:46 +0800335 Table table;
John Wangf719f3b2020-01-17 08:46:22 +0800336 biosStringTable.load(table);
John Wangdd9a6282019-10-11 18:52:46 +0800337 auto stringEntry = pldm_bios_table_string_find_by_handle(
338 table.data(), table.size(), stringHdl);
John Wangdd9a6282019-10-11 18:52:46 +0800339 if (stringEntry == nullptr)
Sampa Misrab37be312019-07-03 02:26:41 -0500340 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600341 std::cerr << "Reached end of BIOS string table,did not find "
342 << "string name for handle, STRING_HANDLE=" << stringHdl
343 << "\n";
John Wang88a349c2020-01-20 14:19:49 +0800344 throw InternalFailure();
Sampa Misrab37be312019-07-03 02:26:41 -0500345 }
John Wangdd9a6282019-10-11 18:52:46 +0800346 auto strLength =
347 pldm_bios_table_string_entry_decode_string_length(stringEntry);
John Wang88a349c2020-01-20 14:19:49 +0800348 std::vector<char> buffer(strLength + 1);
349 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
350 buffer.size());
351
352 return std::string(buffer.data(), buffer.data() + strLength);
Sampa Misrab37be312019-07-03 02:26:41 -0500353}
354
355namespace bios_type_enum
356{
357
Carol Wangdc220c82019-08-26 13:31:31 +0800358using namespace bios_parser::bios_enum;
359
Sampa Misrab37be312019-07-03 02:26:41 -0500360/** @brief Find the indices into the array of the possible values of string
361 * handles for the current values.This is used in attribute value table
362 *
363 * @param[in] possiVals - vector of string handles comprising all the possible
364 * values for an attribute
365 * @param[in] currVals - vector of strings comprising all current values
366 * for an attribute
John Wangf719f3b2020-01-17 08:46:22 +0800367 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500368 *
369 * @return - std::vector<uint8_t> - indices into the array of the possible
370 * values of string handles
371 */
372std::vector<uint8_t> findStrIndices(PossibleValuesByHandle possiVals,
373 CurrentValues currVals,
John Wangf719f3b2020-01-17 08:46:22 +0800374 const BIOSTable& biosStringTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500375{
376 std::vector<uint8_t> stringIndices;
377
378 for (const auto& currVal : currVals)
379 {
380 StringHandle curHdl;
381 try
382 {
John Wangf719f3b2020-01-17 08:46:22 +0800383 curHdl = findStringHandle(currVal, biosStringTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500384 }
385 catch (InternalFailure& e)
386 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600387 std::cerr << "Exception fetching handle for the string, STRING="
388 << currVal.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500389 continue;
390 }
391
392 uint8_t i = 0;
393 for (auto possiHdl : possiVals)
394 {
395 if (possiHdl == curHdl)
396 {
397 stringIndices.push_back(i);
398 break;
399 }
400 i++;
401 }
402 }
403 return stringIndices;
404}
405
406/** @brief Find the indices into the array of the possible values of string
407 * handles for the default values. This is used in attribute table
408 *
409 * @param[in] possiVals - vector of strings comprising all the possible values
410 * for an attribute
411 * @param[in] defVals - vector of strings comprising all the default values
412 * for an attribute
413 * @return - std::vector<uint8_t> - indices into the array of the possible
414 * values of string
415 */
416std::vector<uint8_t> findDefaultValHandle(const PossibleValues& possiVals,
417 const DefaultValues& defVals)
418{
419 std::vector<uint8_t> defHdls;
420 for (const auto& defs : defVals)
421 {
422 auto index = std::lower_bound(possiVals.begin(), possiVals.end(), defs);
423 if (index != possiVals.end())
424 {
425 defHdls.push_back(index - possiVals.begin());
426 }
427 }
428
429 return defHdls;
430}
431
432/** @brief Construct the attibute table for BIOS type Enumeration and
433 * Enumeration ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800434 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500435 * @param[in] biosJsonDir - path where the BIOS json files are present
Carol Wangdc220c82019-08-26 13:31:31 +0800436 * @param[in,out] attributeTable - the attribute table
Sampa Misrab37be312019-07-03 02:26:41 -0500437 *
Sampa Misrab37be312019-07-03 02:26:41 -0500438 */
John Wangf719f3b2020-01-17 08:46:22 +0800439void constructAttrTable(const BIOSTable& biosStringTable, Table& attributeTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500440{
Sampa Misrab37be312019-07-03 02:26:41 -0500441 const auto& attributeMap = getValues();
Sampa Misrab37be312019-07-03 02:26:41 -0500442 StringHandle strHandle;
443
444 for (const auto& [key, value] : attributeMap)
445 {
446 try
447 {
John Wangf719f3b2020-01-17 08:46:22 +0800448 strHandle = findStringHandle(key, biosStringTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500449 }
450 catch (InternalFailure& e)
451 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600452 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
453 << key.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500454 continue;
455 }
John Wangccc04552019-10-14 14:28:25 +0800456 bool readOnly = (std::get<0>(value));
Sampa Misrab37be312019-07-03 02:26:41 -0500457 PossibleValues possiVals = std::get<1>(value);
458 DefaultValues defVals = std::get<2>(value);
459 // both the possible and default values are stored in sorted manner to
460 // ease in fetching back/comparison
461 std::sort(possiVals.begin(), possiVals.end());
462 std::sort(defVals.begin(), defVals.end());
463
464 std::vector<StringHandle> possiValsByHdl;
465 for (const auto& elem : possiVals)
466 {
467 try
468 {
John Wangf719f3b2020-01-17 08:46:22 +0800469 auto hdl = findStringHandle(elem, biosStringTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500470 possiValsByHdl.push_back(std::move(hdl));
471 }
472 catch (InternalFailure& e)
473 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600474 std::cerr << "Could not find handle for BIOS string, STRING="
475 << elem.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500476 continue;
477 }
478 }
479 auto defValsByHdl = findDefaultValHandle(possiVals, defVals);
John Wangccc04552019-10-14 14:28:25 +0800480 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
481 possiValsByHdl.size(), defValsByHdl.size());
Sampa Misrab37be312019-07-03 02:26:41 -0500482
John Wangccc04552019-10-14 14:28:25 +0800483 auto attrTableSize = attributeTable.size();
484 attributeTable.resize(attrTableSize + entryLength, 0);
485 struct pldm_bios_table_attr_entry_enum_info info = {
486 strHandle,
487 readOnly,
488 (uint8_t)possiValsByHdl.size(),
489 possiValsByHdl.data(),
490 (uint8_t)defValsByHdl.size(),
491 defValsByHdl.data(),
492 };
493 pldm_bios_table_attr_entry_enum_encode(
494 attributeTable.data() + attrTableSize, entryLength, &info);
Sampa Misrab37be312019-07-03 02:26:41 -0500495 }
Sampa Misrab37be312019-07-03 02:26:41 -0500496}
497
John Wang3ad21752019-10-06 16:42:21 +0800498void constructAttrValueEntry(
499 const struct pldm_bios_attr_table_entry* attrTableEntry,
John Wangf719f3b2020-01-17 08:46:22 +0800500 const std::string& attrName, const BIOSTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800501 Table& attrValueTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500502{
John Wang3ad21752019-10-06 16:42:21 +0800503 CurrentValues currVals;
504 try
Sampa Misrab37be312019-07-03 02:26:41 -0500505 {
John Wang3ad21752019-10-06 16:42:21 +0800506 currVals = getAttrValue(attrName);
Sampa Misrab37be312019-07-03 02:26:41 -0500507 }
John Wang3ad21752019-10-06 16:42:21 +0800508 catch (const std::exception& e)
509 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600510 std::cerr << "getAttrValue returned error for attribute, NAME="
511 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800512 return;
513 }
514 uint8_t pv_num =
515 pldm_bios_table_attr_entry_enum_decode_pv_num(attrTableEntry);
516 PossibleValuesByHandle pvHdls(pv_num, 0);
517 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrTableEntry,
518 pvHdls.data(), pv_num);
519 std::sort(currVals.begin(), currVals.end());
520
John Wangf719f3b2020-01-17 08:46:22 +0800521 auto currValStrIndices = findStrIndices(pvHdls, currVals, biosStringTable);
John Wang3ad21752019-10-06 16:42:21 +0800522
523 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
524 currValStrIndices.size());
525 auto tableSize = attrValueTable.size();
526 attrValueTable.resize(tableSize + entryLength);
527 pldm_bios_table_attr_value_entry_encode_enum(
528 attrValueTable.data() + tableSize, entryLength,
529 attrTableEntry->attr_handle, attrTableEntry->attr_type,
530 currValStrIndices.size(), currValStrIndices.data());
Sampa Misrab37be312019-07-03 02:26:41 -0500531}
532
533} // end namespace bios_type_enum
534
Carol Wangdc220c82019-08-26 13:31:31 +0800535namespace bios_type_string
536{
Carol Wang612f35b2019-08-26 17:14:26 +0800537
538using namespace bios_parser::bios_string;
539
Carol Wangdc220c82019-08-26 13:31:31 +0800540/** @brief Construct the attibute table for BIOS type String and
541 * String ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800542 * @param[in] biosStringTable - the string table
Carol Wangdc220c82019-08-26 13:31:31 +0800543 * @param[in] biosJsonDir - path where the BIOS json files are present
544 * @param[in,out] attributeTable - the attribute table
545 *
546 */
John Wangf719f3b2020-01-17 08:46:22 +0800547void constructAttrTable(const BIOSTable& biosStringTable, Table& attributeTable)
Carol Wangdc220c82019-08-26 13:31:31 +0800548{
Carol Wang612f35b2019-08-26 17:14:26 +0800549 const auto& attributeMap = getValues();
550 StringHandle strHandle;
Carol Wang612f35b2019-08-26 17:14:26 +0800551 for (const auto& [key, value] : attributeMap)
552 {
553 try
554 {
John Wangf719f3b2020-01-17 08:46:22 +0800555 strHandle = findStringHandle(key, biosStringTable);
Carol Wang612f35b2019-08-26 17:14:26 +0800556 }
557 catch (InternalFailure& e)
558 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600559 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
560 << key.c_str() << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +0800561 continue;
562 }
563
John Wangccc04552019-10-14 14:28:25 +0800564 const auto& [readOnly, strType, minStrLen, maxStrLen, defaultStrLen,
Carol Wang612f35b2019-08-26 17:14:26 +0800565 defaultStr] = value;
John Wangccc04552019-10-14 14:28:25 +0800566 auto entryLength =
567 pldm_bios_table_attr_entry_string_encode_length(defaultStrLen);
Carol Wang612f35b2019-08-26 17:14:26 +0800568
John Wangccc04552019-10-14 14:28:25 +0800569 struct pldm_bios_table_attr_entry_string_info info = {
570 strHandle, readOnly, strType, minStrLen,
571 maxStrLen, defaultStrLen, defaultStr.data(),
572 };
573 auto attrTableSize = attributeTable.size();
574 attributeTable.resize(attrTableSize + entryLength, 0);
575 pldm_bios_table_attr_entry_string_encode(
576 attributeTable.data() + attrTableSize, entryLength, &info);
Carol Wang612f35b2019-08-26 17:14:26 +0800577 }
Carol Wangdc220c82019-08-26 13:31:31 +0800578}
Carol Wangb503f9e2019-09-02 16:34:10 +0800579
John Wang3ad21752019-10-06 16:42:21 +0800580void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
581 const std::string& attrName,
John Wangf719f3b2020-01-17 08:46:22 +0800582 const BIOSTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800583 Table& attrValueTable)
Carol Wangb503f9e2019-09-02 16:34:10 +0800584{
John Wangf719f3b2020-01-17 08:46:22 +0800585 std::ignore = biosStringTable;
John Wang3ad21752019-10-06 16:42:21 +0800586 std::string currStr;
587 uint16_t currStrLen = 0;
588 try
Carol Wangb503f9e2019-09-02 16:34:10 +0800589 {
John Wang3ad21752019-10-06 16:42:21 +0800590 currStr = getAttrValue(attrName);
591 currStrLen = currStr.size();
Carol Wangb503f9e2019-09-02 16:34:10 +0800592 }
John Wang3ad21752019-10-06 16:42:21 +0800593 catch (const std::exception& e)
594 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600595 std::cerr << "getAttrValue returned error for attribute, NAME="
596 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800597 return;
598 }
599 auto entryLength =
600 pldm_bios_table_attr_value_entry_encode_string_length(currStrLen);
601 auto tableSize = attrValueTable.size();
602 attrValueTable.resize(tableSize + entryLength);
603 pldm_bios_table_attr_value_entry_encode_string(
604 attrValueTable.data() + tableSize, entryLength,
605 attrTableEntry->attr_handle, attrTableEntry->attr_type, currStrLen,
606 currStr.c_str());
Carol Wangb503f9e2019-09-02 16:34:10 +0800607}
608
Carol Wangdc220c82019-08-26 13:31:31 +0800609} // end namespace bios_type_string
610
John Wangdbbc9ff2019-10-25 13:53:46 +0800611namespace bios_type_integer
612{
613
614using namespace bios_parser::bios_integer;
615
616/** @brief Construct the attibute table for BIOS type Integer and
617 * Integer ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800618 * @param[in] biosStringTable - the string table
John Wangdbbc9ff2019-10-25 13:53:46 +0800619 * @param[in,out] attributeTable - the attribute table
620 *
621 */
John Wangf719f3b2020-01-17 08:46:22 +0800622void constructAttrTable(const BIOSTable& biosStringTable, Table& attributeTable)
John Wangdbbc9ff2019-10-25 13:53:46 +0800623{
624 const auto& attributeMap = getValues();
625 StringHandle strHandle;
626 for (const auto& [key, value] : attributeMap)
627 {
628 try
629 {
John Wangf719f3b2020-01-17 08:46:22 +0800630 strHandle = findStringHandle(key, biosStringTable);
John Wangdbbc9ff2019-10-25 13:53:46 +0800631 }
632 catch (InternalFailure& e)
633 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600634 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
635 << key.c_str() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800636 continue;
637 }
638
639 const auto& [readOnly, lowerBound, upperBound, scalarIncrement,
640 defaultValue] = value;
641 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
642
643 struct pldm_bios_table_attr_entry_integer_info info = {
644 strHandle, readOnly, lowerBound,
645 upperBound, scalarIncrement, defaultValue,
646 };
647 auto attrTableSize = attributeTable.size();
648 attributeTable.resize(attrTableSize + entryLength, 0);
649 pldm_bios_table_attr_entry_integer_encode(
650 attributeTable.data() + attrTableSize, entryLength, &info);
651 }
652}
653
654void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
655 const std::string& attrName,
John Wangf719f3b2020-01-17 08:46:22 +0800656 const BIOSTable& biosStringTable,
John Wangdbbc9ff2019-10-25 13:53:46 +0800657 Table& attrValueTable)
658{
John Wangf719f3b2020-01-17 08:46:22 +0800659 std::ignore = biosStringTable;
John Wangdbbc9ff2019-10-25 13:53:46 +0800660 uint64_t currentValue;
661 try
662 {
663 currentValue = getAttrValue(attrName);
664 }
665 catch (const std::exception& e)
666 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600667 std::cerr << "Failed to get attribute value, NAME=" << attrName.c_str()
668 << " ERROR=" << e.what() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800669 return;
670 }
671 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
672 auto tableSize = attrValueTable.size();
673 attrValueTable.resize(tableSize + entryLength);
674 pldm_bios_table_attr_value_entry_encode_integer(
675 attrValueTable.data() + tableSize, entryLength,
676 attrTableEntry->attr_handle, attrTableEntry->attr_type, currentValue);
677}
678
679} // namespace bios_type_integer
680
John Wang02700402019-10-06 16:34:29 +0800681void traverseBIOSAttrTable(const Table& biosAttrTable,
682 AttrTableEntryHandler handler)
683{
684 std::unique_ptr<pldm_bios_table_iter, decltype(&pldm_bios_table_iter_free)>
685 iter(pldm_bios_table_iter_create(biosAttrTable.data(),
686 biosAttrTable.size(),
687 PLDM_BIOS_ATTR_TABLE),
688 pldm_bios_table_iter_free);
689 while (!pldm_bios_table_iter_is_end(iter.get()))
690 {
691 auto table_entry = pldm_bios_table_iter_attr_entry_value(iter.get());
692 try
693 {
694 handler(table_entry);
695 }
696 catch (const std::exception& e)
697 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600698 std::cerr << "handler fails when traversing BIOSAttrTable, ERROR="
699 << e.what() << "\n";
John Wang02700402019-10-06 16:34:29 +0800700 }
701 pldm_bios_table_iter_next(iter.get());
702 }
703}
704
John Wangf719f3b2020-01-17 08:46:22 +0800705using typeHandler = std::function<void(const BIOSTable& biosStringTable,
John Wange96e7e52019-10-05 17:47:30 +0800706 Table& attributeTable)>;
Carol Wangdc220c82019-08-26 13:31:31 +0800707std::map<BIOSJsonName, typeHandler> attrTypeHandlers{
708 {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrTable},
John Wangdbbc9ff2019-10-25 13:53:46 +0800709 {bios_parser::bIOSStrJson, bios_type_string::constructAttrTable},
710 {bios_parser::bIOSIntegerJson, bios_type_integer::constructAttrTable},
711};
Carol Wangdc220c82019-08-26 13:31:31 +0800712
Sampa Misrab37be312019-07-03 02:26:41 -0500713/** @brief Construct the BIOS attribute table
714 *
John Wangf719f3b2020-01-17 08:46:22 +0800715 * @param[in,out] biosAttributeTable - the attribute table
716 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500717 * @param[in] biosJsonDir - path where the BIOS json files are present
George Liufb8611d2019-12-06 10:14:15 +0800718 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500719 */
John Wangf719f3b2020-01-17 08:46:22 +0800720Response getBIOSAttributeTable(BIOSTable& biosAttributeTable,
721 const BIOSTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800722 const char* biosJsonDir, const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500723{
724 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
725 0);
726 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
727 uint32_t nxtTransferHandle = 0;
728 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500729
John Wangf719f3b2020-01-17 08:46:22 +0800730 if (biosAttributeTable.isEmpty())
Sampa Misrab37be312019-07-03 02:26:41 -0500731 { // no persisted table, constructing fresh table and response
Carol Wangdc220c82019-08-26 13:31:31 +0800732 Table attributeTable;
733 fs::path dir(biosJsonDir);
734
735 for (auto it = attrTypeHandlers.begin(); it != attrTypeHandlers.end();
736 it++)
737 {
738 fs::path file = dir / it->first;
739 if (fs::exists(file))
740 {
John Wangf719f3b2020-01-17 08:46:22 +0800741 it->second(biosStringTable, attributeTable);
Carol Wangdc220c82019-08-26 13:31:31 +0800742 }
743 }
744
745 if (attributeTable.empty())
746 { // no available json file is found
George Liufb8611d2019-12-06 10:14:15 +0800747 return CmdHandler::ccOnlyResponse(request,
748 PLDM_BIOS_TABLE_UNAVAILABLE);
Carol Wangdc220c82019-08-26 13:31:31 +0800749 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600750 pldm::responder::utils::padAndChecksum(attributeTable);
John Wangf719f3b2020-01-17 08:46:22 +0800751 biosAttributeTable.store(attributeTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500752 response.resize(sizeof(pldm_msg_hdr) +
753 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
754 attributeTable.size());
755 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800756
757 auto rc = encode_get_bios_table_resp(
758 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
759 transferFlag, attributeTable.data(), response.size(), responsePtr);
760 if (rc != PLDM_SUCCESS)
761 {
762 return CmdHandler::ccOnlyResponse(request, rc);
763 }
Sampa Misrab37be312019-07-03 02:26:41 -0500764 }
765 else
766 { // persisted table present, constructing response
George Liufb8611d2019-12-06 10:14:15 +0800767 auto rc = encode_get_bios_table_resp(
768 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
769 transferFlag, nullptr, response.size(),
770 responsePtr); // filling up the header here
771 if (rc != PLDM_SUCCESS)
772 {
773 return CmdHandler::ccOnlyResponse(request, rc);
774 }
John Wangf719f3b2020-01-17 08:46:22 +0800775 biosAttributeTable.load(response);
Sampa Misrab37be312019-07-03 02:26:41 -0500776 }
777
778 return response;
779}
780
John Wang3ad21752019-10-06 16:42:21 +0800781using AttrValTableEntryConstructHandler =
782 std::function<void(const struct pldm_bios_attr_table_entry* tableEntry,
783 const std::string& attrName,
John Wangf719f3b2020-01-17 08:46:22 +0800784 const BIOSTable& biosStringTable, Table& table)>;
John Wang3ad21752019-10-06 16:42:21 +0800785
786using AttrType = uint8_t;
787const std::map<AttrType, AttrValTableEntryConstructHandler>
788 AttrValTableConstructMap{
789 {PLDM_BIOS_STRING, bios_type_string::constructAttrValueEntry},
790 {PLDM_BIOS_STRING_READ_ONLY, bios_type_string::constructAttrValueEntry},
791 {PLDM_BIOS_ENUMERATION, bios_type_enum::constructAttrValueEntry},
792 {PLDM_BIOS_ENUMERATION_READ_ONLY,
793 bios_type_enum::constructAttrValueEntry},
John Wangdbbc9ff2019-10-25 13:53:46 +0800794 {PLDM_BIOS_INTEGER, bios_type_integer::constructAttrValueEntry},
795 {PLDM_BIOS_INTEGER_READ_ONLY,
796 bios_type_integer::constructAttrValueEntry},
John Wang3ad21752019-10-06 16:42:21 +0800797 };
798
799void constructAttrValueTableEntry(
800 const struct pldm_bios_attr_table_entry* attrEntry,
John Wangf719f3b2020-01-17 08:46:22 +0800801 const BIOSTable& biosStringTable, Table& attributeValueTable)
John Wang3ad21752019-10-06 16:42:21 +0800802{
John Wangf719f3b2020-01-17 08:46:22 +0800803 auto attrName = findStringName(attrEntry->string_handle, biosStringTable);
John Wang3ad21752019-10-06 16:42:21 +0800804 if (attrName.empty())
805 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600806 std::cerr << "invalid string handle, STRING_HANDLE="
807 << attrEntry->string_handle << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800808 return;
809 }
810
811 AttrValTableConstructMap.at(attrEntry->attr_type)(
John Wangf719f3b2020-01-17 08:46:22 +0800812 attrEntry, attrName, biosStringTable, attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800813}
814
Sampa Misrab37be312019-07-03 02:26:41 -0500815/** @brief Construct the BIOS attribute value table
816 *
John Wangf719f3b2020-01-17 08:46:22 +0800817 * @param[in,out] biosAttributeValueTable - the attribute value table
818 * @param[in] biosAttributeTable - the attribute table
819 * @param[in] biosStringTable - the string table
George Liufb8611d2019-12-06 10:14:15 +0800820 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500821 */
John Wangf719f3b2020-01-17 08:46:22 +0800822Response getBIOSAttributeValueTable(BIOSTable& biosAttributeValueTable,
823 const BIOSTable& biosAttributeTable,
824 const BIOSTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800825 const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500826{
827 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
828 0);
829 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
830 uint32_t nxtTransferHandle = 0;
831 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500832
John Wangf719f3b2020-01-17 08:46:22 +0800833 if (!biosAttributeValueTable.isEmpty())
John Wang3ad21752019-10-06 16:42:21 +0800834 {
George Liufb8611d2019-12-06 10:14:15 +0800835 auto rc = encode_get_bios_table_resp(
836 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
837 transferFlag, nullptr, response.size(),
838 responsePtr); // filling up the header here
839 if (rc != PLDM_SUCCESS)
840 {
841 return CmdHandler::ccOnlyResponse(request, rc);
842 }
843
John Wangf719f3b2020-01-17 08:46:22 +0800844 biosAttributeValueTable.load(response);
John Wang3ad21752019-10-06 16:42:21 +0800845 return response;
Sampa Misrab37be312019-07-03 02:26:41 -0500846 }
847
John Wang3ad21752019-10-06 16:42:21 +0800848 Table attributeValueTable;
849 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800850 biosAttributeTable.load(attributeTable);
John Wang3ad21752019-10-06 16:42:21 +0800851 traverseBIOSAttrTable(
852 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800853 [&biosStringTable, &attributeValueTable](
John Wang3ad21752019-10-06 16:42:21 +0800854 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800855 constructAttrValueTableEntry(tableEntry, biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800856 attributeValueTable);
857 });
858 if (attributeValueTable.empty())
859 {
George Liufb8611d2019-12-06 10:14:15 +0800860 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wang3ad21752019-10-06 16:42:21 +0800861 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600862 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800863 biosAttributeValueTable.store(attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800864
865 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
866 attributeValueTable.size());
867 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800868 auto rc = encode_get_bios_table_resp(
869 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle, transferFlag,
870 attributeValueTable.data(), response.size(), responsePtr);
871 if (rc != PLDM_SUCCESS)
872 {
873 return CmdHandler::ccOnlyResponse(request, rc);
874 }
John Wang3ad21752019-10-06 16:42:21 +0800875
Sampa Misrab37be312019-07-03 02:26:41 -0500876 return response;
877}
878
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600879Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500880{
Deepak Kodihallic3d20892019-08-01 05:38:31 -0500881 fs::create_directory(BIOS_TABLES_DIR);
Sampa Misrab37be312019-07-03 02:26:41 -0500882 auto response = internal::buildBIOSTables(request, payloadLength,
883 BIOS_JSONS_DIR, BIOS_TABLES_DIR);
884
885 return response;
886}
887
John Wang8721ed62019-12-05 14:44:43 +0800888Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
889 size_t payloadLength)
890{
891 uint32_t transferHandle;
892 uint8_t transferOpFlag;
893 uint16_t attributeHandle;
894
895 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
896 request, payloadLength, &transferHandle, &transferOpFlag,
897 &attributeHandle);
898 if (rc != PLDM_SUCCESS)
899 {
900 return ccOnlyResponse(request, rc);
901 }
902
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600903 fs::path tablesPath(BIOS_TABLES_DIR);
904 auto stringTablePath = tablesPath / stringTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800905 BIOSTable biosStringTable(stringTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600906 auto attrTablePath = tablesPath / attrTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800907 BIOSTable biosAttributeTable(attrTablePath.c_str());
908 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600909 {
910 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
911 }
912
913 auto attrValueTablePath = tablesPath / attrValTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800914 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600915
John Wangf719f3b2020-01-17 08:46:22 +0800916 if (biosAttributeValueTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600917 {
918 Table attributeValueTable;
919 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800920 biosAttributeTable.load(attributeTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600921 traverseBIOSAttrTable(
922 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800923 [&biosStringTable, &attributeValueTable](
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600924 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800925 constructAttrValueTableEntry(tableEntry, biosStringTable,
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600926 attributeValueTable);
927 });
928 if (attributeValueTable.empty())
929 {
930 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
931 }
932 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800933 biosAttributeValueTable.store(attributeValueTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600934 }
John Wang8721ed62019-12-05 14:44:43 +0800935
936 Response table;
John Wangf719f3b2020-01-17 08:46:22 +0800937 biosAttributeValueTable.load(table);
John Wang8721ed62019-12-05 14:44:43 +0800938
939 auto entry = pldm_bios_table_attr_value_find_by_handle(
940 table.data(), table.size(), attributeHandle);
941 if (entry == nullptr)
942 {
943 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
944 }
945
John Wang8e877e02020-02-03 16:06:55 +0800946 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800947 Response response(sizeof(pldm_msg_hdr) +
948 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800949 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800950 0);
951 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800952 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800953 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
954 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800955 if (rc != PLDM_SUCCESS)
956 {
957 return ccOnlyResponse(request, rc);
958 }
John Wang8721ed62019-12-05 14:44:43 +0800959
960 return response;
961}
962
John Wang42174882019-12-20 14:56:59 +0800963Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
964 size_t payloadLength)
965{
966 uint32_t transferHandle;
967 uint8_t transferOpFlag;
968 variable_field attributeField;
969
970 auto rc = decode_set_bios_attribute_current_value_req(
971 request, payloadLength, &transferHandle, &transferOpFlag,
972 &attributeField);
973 if (rc != PLDM_SUCCESS)
974 {
975 return ccOnlyResponse(request, rc);
976 }
977
978 fs::path tablesPath(BIOS_TABLES_DIR);
979 auto stringTablePath = tablesPath / stringTableFile;
980 BIOSStringTable biosStringTable(stringTablePath.c_str());
981 auto attrTablePath = tablesPath / attrTableFile;
982 BIOSTable biosAttributeTable(attrTablePath.c_str());
983 auto attrValueTablePath = tablesPath / attrValTableFile;
984 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
985 // TODO: Construct attribute value table if it's empty. (another commit)
986
987 Response srcTable;
988 biosAttributeValueTable.load(srcTable);
989
990 // Replace the old attribute with the new attribute, the size of table will
991 // change:
992 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
993 // sizeof(oldAttribute) + pad(4-byte alignment, max =
994 // 3)
995 // For simplicity, we use
996 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
997 size_t destBufferLength = srcTable.size() + attributeField.length + 3;
998 Response destTable(destBufferLength);
999 size_t destTableLen = destTable.size();
1000
1001 rc = pldm_bios_table_attr_value_copy_and_update(
1002 srcTable.data(), srcTable.size(), destTable.data(), &destTableLen,
1003 attributeField.ptr, attributeField.length);
1004 destTable.resize(destTableLen);
1005
1006 if (rc != PLDM_SUCCESS)
1007 {
1008 return ccOnlyResponse(request, rc);
1009 }
1010
1011 rc = setAttributeValueOnDbus(&attributeField, biosAttributeTable,
1012 biosStringTable);
1013 if (rc != PLDM_SUCCESS)
1014 {
1015 return ccOnlyResponse(request, rc);
1016 }
1017
1018 biosAttributeValueTable.store(destTable);
1019
1020 return ccOnlyResponse(request, PLDM_SUCCESS);
1021}
1022
Sampa Misrab37be312019-07-03 02:26:41 -05001023namespace internal
1024{
1025
1026Response buildBIOSTables(const pldm_msg* request, size_t payloadLength,
1027 const char* biosJsonDir, const char* biosTablePath)
1028{
1029 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
1030 0);
Sampa Misrab37be312019-07-03 02:26:41 -05001031
John Wange96e7e52019-10-05 17:47:30 +08001032 if (setupConfig(biosJsonDir) != 0)
1033 {
George Liufb8611d2019-12-06 10:14:15 +08001034 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wange96e7e52019-10-05 17:47:30 +08001035 }
1036
Sampa Misrab37be312019-07-03 02:26:41 -05001037 uint32_t transferHandle{};
1038 uint8_t transferOpFlag{};
1039 uint8_t tableType{};
1040
1041 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
1042 &transferOpFlag, &tableType);
George Liufb8611d2019-12-06 10:14:15 +08001043 if (rc != PLDM_SUCCESS)
Sampa Misrab37be312019-07-03 02:26:41 -05001044 {
George Liufb8611d2019-12-06 10:14:15 +08001045 return CmdHandler::ccOnlyResponse(request, rc);
1046 }
Sampa Misrab37be312019-07-03 02:26:41 -05001047
John Wangf719f3b2020-01-17 08:46:22 +08001048 BIOSTable biosStringTable(
George Liufb8611d2019-12-06 10:14:15 +08001049 (std::string(biosTablePath) + "/" + stringTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001050 BIOSTable biosAttributeTable(
George Liufb8611d2019-12-06 10:14:15 +08001051 (std::string(biosTablePath) + "/" + attrTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001052 BIOSTable biosAttributeValueTable(
George Liufb8611d2019-12-06 10:14:15 +08001053 (std::string(biosTablePath) + "/" + attrValTableFile).c_str());
1054 switch (tableType)
1055 {
1056 case PLDM_BIOS_STRING_TABLE:
Sampa Misrab37be312019-07-03 02:26:41 -05001057
John Wangf719f3b2020-01-17 08:46:22 +08001058 response = getBIOSStringTable(biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001059 break;
1060 case PLDM_BIOS_ATTR_TABLE:
1061
John Wangf719f3b2020-01-17 08:46:22 +08001062 if (biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001063 {
1064 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1065 }
1066 else
1067 {
1068 response = getBIOSAttributeTable(
John Wangf719f3b2020-01-17 08:46:22 +08001069 biosAttributeTable, biosStringTable, biosJsonDir, request);
George Liufb8611d2019-12-06 10:14:15 +08001070 }
1071 break;
1072 case PLDM_BIOS_ATTR_VAL_TABLE:
John Wangf719f3b2020-01-17 08:46:22 +08001073 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001074 {
1075 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1076 }
1077 else
1078 {
John Wangf719f3b2020-01-17 08:46:22 +08001079 response = getBIOSAttributeValueTable(biosAttributeValueTable,
1080 biosAttributeTable,
1081 biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001082 }
1083 break;
1084 default:
1085 rc = PLDM_INVALID_BIOS_TABLE_TYPE;
1086 break;
Sampa Misrab37be312019-07-03 02:26:41 -05001087 }
1088
1089 if (rc != PLDM_SUCCESS)
1090 {
George Liufb8611d2019-12-06 10:14:15 +08001091 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misrab37be312019-07-03 02:26:41 -05001092 }
1093
1094 return response;
1095}
1096
John Wangf719f3b2020-01-17 08:46:22 +08001097} // namespace internal
Sampa Misrab37be312019-07-03 02:26:41 -05001098
John Wangf719f3b2020-01-17 08:46:22 +08001099} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -06001100} // namespace responder
1101} // namespace pldm