blob: 61b5e49d9bbf45d064e029e9dc5c90eceb5d5723 [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 {
John Wang59ef6072020-01-21 13:37:01 +0800422 auto index = std::find_if(possiVals.begin(), possiVals.end(),
423 [&defs](const auto& v) { return defs == v; });
Sampa Misrab37be312019-07-03 02:26:41 -0500424 if (index != possiVals.end())
425 {
426 defHdls.push_back(index - possiVals.begin());
427 }
428 }
429
430 return defHdls;
431}
432
433/** @brief Construct the attibute table for BIOS type Enumeration and
434 * Enumeration ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800435 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500436 * @param[in] biosJsonDir - path where the BIOS json files are present
Carol Wangdc220c82019-08-26 13:31:31 +0800437 * @param[in,out] attributeTable - the attribute table
Sampa Misrab37be312019-07-03 02:26:41 -0500438 *
Sampa Misrab37be312019-07-03 02:26:41 -0500439 */
John Wangf719f3b2020-01-17 08:46:22 +0800440void constructAttrTable(const BIOSTable& biosStringTable, Table& attributeTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500441{
Sampa Misrab37be312019-07-03 02:26:41 -0500442 const auto& attributeMap = getValues();
Sampa Misrab37be312019-07-03 02:26:41 -0500443 StringHandle strHandle;
444
445 for (const auto& [key, value] : attributeMap)
446 {
447 try
448 {
John Wangf719f3b2020-01-17 08:46:22 +0800449 strHandle = findStringHandle(key, biosStringTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500450 }
451 catch (InternalFailure& e)
452 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600453 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
454 << key.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500455 continue;
456 }
John Wangccc04552019-10-14 14:28:25 +0800457 bool readOnly = (std::get<0>(value));
John Wang59ef6072020-01-21 13:37:01 +0800458 const PossibleValues& possiVals = std::get<1>(value);
459 const DefaultValues& defVals = std::get<2>(value);
Sampa Misrab37be312019-07-03 02:26:41 -0500460
461 std::vector<StringHandle> possiValsByHdl;
462 for (const auto& elem : possiVals)
463 {
464 try
465 {
John Wangf719f3b2020-01-17 08:46:22 +0800466 auto hdl = findStringHandle(elem, biosStringTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500467 possiValsByHdl.push_back(std::move(hdl));
468 }
469 catch (InternalFailure& e)
470 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600471 std::cerr << "Could not find handle for BIOS string, STRING="
472 << elem.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500473 continue;
474 }
475 }
476 auto defValsByHdl = findDefaultValHandle(possiVals, defVals);
John Wangccc04552019-10-14 14:28:25 +0800477 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
478 possiValsByHdl.size(), defValsByHdl.size());
Sampa Misrab37be312019-07-03 02:26:41 -0500479
John Wangccc04552019-10-14 14:28:25 +0800480 auto attrTableSize = attributeTable.size();
481 attributeTable.resize(attrTableSize + entryLength, 0);
482 struct pldm_bios_table_attr_entry_enum_info info = {
483 strHandle,
484 readOnly,
485 (uint8_t)possiValsByHdl.size(),
486 possiValsByHdl.data(),
487 (uint8_t)defValsByHdl.size(),
488 defValsByHdl.data(),
489 };
490 pldm_bios_table_attr_entry_enum_encode(
491 attributeTable.data() + attrTableSize, entryLength, &info);
Sampa Misrab37be312019-07-03 02:26:41 -0500492 }
Sampa Misrab37be312019-07-03 02:26:41 -0500493}
494
John Wang3ad21752019-10-06 16:42:21 +0800495void constructAttrValueEntry(
496 const struct pldm_bios_attr_table_entry* attrTableEntry,
John Wangf719f3b2020-01-17 08:46:22 +0800497 const std::string& attrName, const BIOSTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800498 Table& attrValueTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500499{
John Wang3ad21752019-10-06 16:42:21 +0800500 CurrentValues currVals;
501 try
Sampa Misrab37be312019-07-03 02:26:41 -0500502 {
John Wang3ad21752019-10-06 16:42:21 +0800503 currVals = getAttrValue(attrName);
Sampa Misrab37be312019-07-03 02:26:41 -0500504 }
John Wang3ad21752019-10-06 16:42:21 +0800505 catch (const std::exception& e)
506 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600507 std::cerr << "getAttrValue returned error for attribute, NAME="
508 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800509 return;
510 }
511 uint8_t pv_num =
512 pldm_bios_table_attr_entry_enum_decode_pv_num(attrTableEntry);
513 PossibleValuesByHandle pvHdls(pv_num, 0);
514 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrTableEntry,
515 pvHdls.data(), pv_num);
516 std::sort(currVals.begin(), currVals.end());
517
John Wangf719f3b2020-01-17 08:46:22 +0800518 auto currValStrIndices = findStrIndices(pvHdls, currVals, biosStringTable);
John Wang3ad21752019-10-06 16:42:21 +0800519
520 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
521 currValStrIndices.size());
522 auto tableSize = attrValueTable.size();
523 attrValueTable.resize(tableSize + entryLength);
524 pldm_bios_table_attr_value_entry_encode_enum(
525 attrValueTable.data() + tableSize, entryLength,
526 attrTableEntry->attr_handle, attrTableEntry->attr_type,
527 currValStrIndices.size(), currValStrIndices.data());
Sampa Misrab37be312019-07-03 02:26:41 -0500528}
529
530} // end namespace bios_type_enum
531
Carol Wangdc220c82019-08-26 13:31:31 +0800532namespace bios_type_string
533{
Carol Wang612f35b2019-08-26 17:14:26 +0800534
535using namespace bios_parser::bios_string;
536
Carol Wangdc220c82019-08-26 13:31:31 +0800537/** @brief Construct the attibute table for BIOS type String and
538 * String ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800539 * @param[in] biosStringTable - the string table
Carol Wangdc220c82019-08-26 13:31:31 +0800540 * @param[in] biosJsonDir - path where the BIOS json files are present
541 * @param[in,out] attributeTable - the attribute table
542 *
543 */
John Wangf719f3b2020-01-17 08:46:22 +0800544void constructAttrTable(const BIOSTable& biosStringTable, Table& attributeTable)
Carol Wangdc220c82019-08-26 13:31:31 +0800545{
Carol Wang612f35b2019-08-26 17:14:26 +0800546 const auto& attributeMap = getValues();
547 StringHandle strHandle;
Carol Wang612f35b2019-08-26 17:14:26 +0800548 for (const auto& [key, value] : attributeMap)
549 {
550 try
551 {
John Wangf719f3b2020-01-17 08:46:22 +0800552 strHandle = findStringHandle(key, biosStringTable);
Carol Wang612f35b2019-08-26 17:14:26 +0800553 }
554 catch (InternalFailure& e)
555 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600556 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
557 << key.c_str() << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +0800558 continue;
559 }
560
John Wangccc04552019-10-14 14:28:25 +0800561 const auto& [readOnly, strType, minStrLen, maxStrLen, defaultStrLen,
Carol Wang612f35b2019-08-26 17:14:26 +0800562 defaultStr] = value;
John Wangccc04552019-10-14 14:28:25 +0800563 auto entryLength =
564 pldm_bios_table_attr_entry_string_encode_length(defaultStrLen);
Carol Wang612f35b2019-08-26 17:14:26 +0800565
John Wangccc04552019-10-14 14:28:25 +0800566 struct pldm_bios_table_attr_entry_string_info info = {
567 strHandle, readOnly, strType, minStrLen,
568 maxStrLen, defaultStrLen, defaultStr.data(),
569 };
570 auto attrTableSize = attributeTable.size();
571 attributeTable.resize(attrTableSize + entryLength, 0);
572 pldm_bios_table_attr_entry_string_encode(
573 attributeTable.data() + attrTableSize, entryLength, &info);
Carol Wang612f35b2019-08-26 17:14:26 +0800574 }
Carol Wangdc220c82019-08-26 13:31:31 +0800575}
Carol Wangb503f9e2019-09-02 16:34:10 +0800576
John Wang3ad21752019-10-06 16:42:21 +0800577void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
578 const std::string& attrName,
John Wangf719f3b2020-01-17 08:46:22 +0800579 const BIOSTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800580 Table& attrValueTable)
Carol Wangb503f9e2019-09-02 16:34:10 +0800581{
John Wangf719f3b2020-01-17 08:46:22 +0800582 std::ignore = biosStringTable;
John Wang3ad21752019-10-06 16:42:21 +0800583 std::string currStr;
584 uint16_t currStrLen = 0;
585 try
Carol Wangb503f9e2019-09-02 16:34:10 +0800586 {
John Wang3ad21752019-10-06 16:42:21 +0800587 currStr = getAttrValue(attrName);
588 currStrLen = currStr.size();
Carol Wangb503f9e2019-09-02 16:34:10 +0800589 }
John Wang3ad21752019-10-06 16:42:21 +0800590 catch (const std::exception& e)
591 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600592 std::cerr << "getAttrValue returned error for attribute, NAME="
593 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800594 return;
595 }
596 auto entryLength =
597 pldm_bios_table_attr_value_entry_encode_string_length(currStrLen);
598 auto tableSize = attrValueTable.size();
599 attrValueTable.resize(tableSize + entryLength);
600 pldm_bios_table_attr_value_entry_encode_string(
601 attrValueTable.data() + tableSize, entryLength,
602 attrTableEntry->attr_handle, attrTableEntry->attr_type, currStrLen,
603 currStr.c_str());
Carol Wangb503f9e2019-09-02 16:34:10 +0800604}
605
Carol Wangdc220c82019-08-26 13:31:31 +0800606} // end namespace bios_type_string
607
John Wangdbbc9ff2019-10-25 13:53:46 +0800608namespace bios_type_integer
609{
610
611using namespace bios_parser::bios_integer;
612
613/** @brief Construct the attibute table for BIOS type Integer and
614 * Integer ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800615 * @param[in] biosStringTable - the string table
John Wangdbbc9ff2019-10-25 13:53:46 +0800616 * @param[in,out] attributeTable - the attribute table
617 *
618 */
John Wangf719f3b2020-01-17 08:46:22 +0800619void constructAttrTable(const BIOSTable& biosStringTable, Table& attributeTable)
John Wangdbbc9ff2019-10-25 13:53:46 +0800620{
621 const auto& attributeMap = getValues();
622 StringHandle strHandle;
623 for (const auto& [key, value] : attributeMap)
624 {
625 try
626 {
John Wangf719f3b2020-01-17 08:46:22 +0800627 strHandle = findStringHandle(key, biosStringTable);
John Wangdbbc9ff2019-10-25 13:53:46 +0800628 }
629 catch (InternalFailure& e)
630 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600631 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
632 << key.c_str() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800633 continue;
634 }
635
636 const auto& [readOnly, lowerBound, upperBound, scalarIncrement,
637 defaultValue] = value;
638 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
639
640 struct pldm_bios_table_attr_entry_integer_info info = {
641 strHandle, readOnly, lowerBound,
642 upperBound, scalarIncrement, defaultValue,
643 };
644 auto attrTableSize = attributeTable.size();
645 attributeTable.resize(attrTableSize + entryLength, 0);
646 pldm_bios_table_attr_entry_integer_encode(
647 attributeTable.data() + attrTableSize, entryLength, &info);
648 }
649}
650
651void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
652 const std::string& attrName,
John Wangf719f3b2020-01-17 08:46:22 +0800653 const BIOSTable& biosStringTable,
John Wangdbbc9ff2019-10-25 13:53:46 +0800654 Table& attrValueTable)
655{
John Wangf719f3b2020-01-17 08:46:22 +0800656 std::ignore = biosStringTable;
John Wangdbbc9ff2019-10-25 13:53:46 +0800657 uint64_t currentValue;
658 try
659 {
660 currentValue = getAttrValue(attrName);
661 }
662 catch (const std::exception& e)
663 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600664 std::cerr << "Failed to get attribute value, NAME=" << attrName.c_str()
665 << " ERROR=" << e.what() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800666 return;
667 }
668 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
669 auto tableSize = attrValueTable.size();
670 attrValueTable.resize(tableSize + entryLength);
671 pldm_bios_table_attr_value_entry_encode_integer(
672 attrValueTable.data() + tableSize, entryLength,
673 attrTableEntry->attr_handle, attrTableEntry->attr_type, currentValue);
674}
675
676} // namespace bios_type_integer
677
John Wang02700402019-10-06 16:34:29 +0800678void traverseBIOSAttrTable(const Table& biosAttrTable,
679 AttrTableEntryHandler handler)
680{
681 std::unique_ptr<pldm_bios_table_iter, decltype(&pldm_bios_table_iter_free)>
682 iter(pldm_bios_table_iter_create(biosAttrTable.data(),
683 biosAttrTable.size(),
684 PLDM_BIOS_ATTR_TABLE),
685 pldm_bios_table_iter_free);
686 while (!pldm_bios_table_iter_is_end(iter.get()))
687 {
688 auto table_entry = pldm_bios_table_iter_attr_entry_value(iter.get());
689 try
690 {
691 handler(table_entry);
692 }
693 catch (const std::exception& e)
694 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600695 std::cerr << "handler fails when traversing BIOSAttrTable, ERROR="
696 << e.what() << "\n";
John Wang02700402019-10-06 16:34:29 +0800697 }
698 pldm_bios_table_iter_next(iter.get());
699 }
700}
701
John Wangf719f3b2020-01-17 08:46:22 +0800702using typeHandler = std::function<void(const BIOSTable& biosStringTable,
John Wange96e7e52019-10-05 17:47:30 +0800703 Table& attributeTable)>;
Carol Wangdc220c82019-08-26 13:31:31 +0800704std::map<BIOSJsonName, typeHandler> attrTypeHandlers{
705 {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrTable},
John Wangdbbc9ff2019-10-25 13:53:46 +0800706 {bios_parser::bIOSStrJson, bios_type_string::constructAttrTable},
707 {bios_parser::bIOSIntegerJson, bios_type_integer::constructAttrTable},
708};
Carol Wangdc220c82019-08-26 13:31:31 +0800709
Sampa Misrab37be312019-07-03 02:26:41 -0500710/** @brief Construct the BIOS attribute table
711 *
John Wangf719f3b2020-01-17 08:46:22 +0800712 * @param[in,out] biosAttributeTable - the attribute table
713 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500714 * @param[in] biosJsonDir - path where the BIOS json files are present
George Liufb8611d2019-12-06 10:14:15 +0800715 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500716 */
John Wangf719f3b2020-01-17 08:46:22 +0800717Response getBIOSAttributeTable(BIOSTable& biosAttributeTable,
718 const BIOSTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800719 const char* biosJsonDir, const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500720{
721 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
722 0);
723 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
724 uint32_t nxtTransferHandle = 0;
725 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500726
John Wangf719f3b2020-01-17 08:46:22 +0800727 if (biosAttributeTable.isEmpty())
Sampa Misrab37be312019-07-03 02:26:41 -0500728 { // no persisted table, constructing fresh table and response
Carol Wangdc220c82019-08-26 13:31:31 +0800729 Table attributeTable;
730 fs::path dir(biosJsonDir);
731
732 for (auto it = attrTypeHandlers.begin(); it != attrTypeHandlers.end();
733 it++)
734 {
735 fs::path file = dir / it->first;
736 if (fs::exists(file))
737 {
John Wangf719f3b2020-01-17 08:46:22 +0800738 it->second(biosStringTable, attributeTable);
Carol Wangdc220c82019-08-26 13:31:31 +0800739 }
740 }
741
742 if (attributeTable.empty())
743 { // no available json file is found
George Liufb8611d2019-12-06 10:14:15 +0800744 return CmdHandler::ccOnlyResponse(request,
745 PLDM_BIOS_TABLE_UNAVAILABLE);
Carol Wangdc220c82019-08-26 13:31:31 +0800746 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600747 pldm::responder::utils::padAndChecksum(attributeTable);
John Wangf719f3b2020-01-17 08:46:22 +0800748 biosAttributeTable.store(attributeTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500749 response.resize(sizeof(pldm_msg_hdr) +
750 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
751 attributeTable.size());
752 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800753
754 auto rc = encode_get_bios_table_resp(
755 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
756 transferFlag, attributeTable.data(), response.size(), responsePtr);
757 if (rc != PLDM_SUCCESS)
758 {
759 return CmdHandler::ccOnlyResponse(request, rc);
760 }
Sampa Misrab37be312019-07-03 02:26:41 -0500761 }
762 else
763 { // persisted table present, constructing response
George Liufb8611d2019-12-06 10:14:15 +0800764 auto rc = encode_get_bios_table_resp(
765 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
766 transferFlag, nullptr, response.size(),
767 responsePtr); // filling up the header here
768 if (rc != PLDM_SUCCESS)
769 {
770 return CmdHandler::ccOnlyResponse(request, rc);
771 }
John Wangf719f3b2020-01-17 08:46:22 +0800772 biosAttributeTable.load(response);
Sampa Misrab37be312019-07-03 02:26:41 -0500773 }
774
775 return response;
776}
777
John Wang3ad21752019-10-06 16:42:21 +0800778using AttrValTableEntryConstructHandler =
779 std::function<void(const struct pldm_bios_attr_table_entry* tableEntry,
780 const std::string& attrName,
John Wangf719f3b2020-01-17 08:46:22 +0800781 const BIOSTable& biosStringTable, Table& table)>;
John Wang3ad21752019-10-06 16:42:21 +0800782
783using AttrType = uint8_t;
784const std::map<AttrType, AttrValTableEntryConstructHandler>
785 AttrValTableConstructMap{
786 {PLDM_BIOS_STRING, bios_type_string::constructAttrValueEntry},
787 {PLDM_BIOS_STRING_READ_ONLY, bios_type_string::constructAttrValueEntry},
788 {PLDM_BIOS_ENUMERATION, bios_type_enum::constructAttrValueEntry},
789 {PLDM_BIOS_ENUMERATION_READ_ONLY,
790 bios_type_enum::constructAttrValueEntry},
John Wangdbbc9ff2019-10-25 13:53:46 +0800791 {PLDM_BIOS_INTEGER, bios_type_integer::constructAttrValueEntry},
792 {PLDM_BIOS_INTEGER_READ_ONLY,
793 bios_type_integer::constructAttrValueEntry},
John Wang3ad21752019-10-06 16:42:21 +0800794 };
795
796void constructAttrValueTableEntry(
797 const struct pldm_bios_attr_table_entry* attrEntry,
John Wangf719f3b2020-01-17 08:46:22 +0800798 const BIOSTable& biosStringTable, Table& attributeValueTable)
John Wang3ad21752019-10-06 16:42:21 +0800799{
John Wangf719f3b2020-01-17 08:46:22 +0800800 auto attrName = findStringName(attrEntry->string_handle, biosStringTable);
John Wang3ad21752019-10-06 16:42:21 +0800801 if (attrName.empty())
802 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600803 std::cerr << "invalid string handle, STRING_HANDLE="
804 << attrEntry->string_handle << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800805 return;
806 }
807
808 AttrValTableConstructMap.at(attrEntry->attr_type)(
John Wangf719f3b2020-01-17 08:46:22 +0800809 attrEntry, attrName, biosStringTable, attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800810}
811
Sampa Misrab37be312019-07-03 02:26:41 -0500812/** @brief Construct the BIOS attribute value table
813 *
John Wangf719f3b2020-01-17 08:46:22 +0800814 * @param[in,out] biosAttributeValueTable - the attribute value table
815 * @param[in] biosAttributeTable - the attribute table
816 * @param[in] biosStringTable - the string table
George Liufb8611d2019-12-06 10:14:15 +0800817 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500818 */
John Wangf719f3b2020-01-17 08:46:22 +0800819Response getBIOSAttributeValueTable(BIOSTable& biosAttributeValueTable,
820 const BIOSTable& biosAttributeTable,
821 const BIOSTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800822 const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500823{
824 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
825 0);
826 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
827 uint32_t nxtTransferHandle = 0;
828 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500829
John Wangf719f3b2020-01-17 08:46:22 +0800830 if (!biosAttributeValueTable.isEmpty())
John Wang3ad21752019-10-06 16:42:21 +0800831 {
George Liufb8611d2019-12-06 10:14:15 +0800832 auto rc = encode_get_bios_table_resp(
833 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
834 transferFlag, nullptr, response.size(),
835 responsePtr); // filling up the header here
836 if (rc != PLDM_SUCCESS)
837 {
838 return CmdHandler::ccOnlyResponse(request, rc);
839 }
840
John Wangf719f3b2020-01-17 08:46:22 +0800841 biosAttributeValueTable.load(response);
John Wang3ad21752019-10-06 16:42:21 +0800842 return response;
Sampa Misrab37be312019-07-03 02:26:41 -0500843 }
844
John Wang3ad21752019-10-06 16:42:21 +0800845 Table attributeValueTable;
846 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800847 biosAttributeTable.load(attributeTable);
John Wang3ad21752019-10-06 16:42:21 +0800848 traverseBIOSAttrTable(
849 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800850 [&biosStringTable, &attributeValueTable](
John Wang3ad21752019-10-06 16:42:21 +0800851 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800852 constructAttrValueTableEntry(tableEntry, biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800853 attributeValueTable);
854 });
855 if (attributeValueTable.empty())
856 {
George Liufb8611d2019-12-06 10:14:15 +0800857 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wang3ad21752019-10-06 16:42:21 +0800858 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600859 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800860 biosAttributeValueTable.store(attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800861
862 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
863 attributeValueTable.size());
864 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800865 auto rc = encode_get_bios_table_resp(
866 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle, transferFlag,
867 attributeValueTable.data(), response.size(), responsePtr);
868 if (rc != PLDM_SUCCESS)
869 {
870 return CmdHandler::ccOnlyResponse(request, rc);
871 }
John Wang3ad21752019-10-06 16:42:21 +0800872
Sampa Misrab37be312019-07-03 02:26:41 -0500873 return response;
874}
875
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600876Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500877{
Deepak Kodihallic3d20892019-08-01 05:38:31 -0500878 fs::create_directory(BIOS_TABLES_DIR);
Sampa Misrab37be312019-07-03 02:26:41 -0500879 auto response = internal::buildBIOSTables(request, payloadLength,
880 BIOS_JSONS_DIR, BIOS_TABLES_DIR);
881
882 return response;
883}
884
John Wang8721ed62019-12-05 14:44:43 +0800885Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
886 size_t payloadLength)
887{
888 uint32_t transferHandle;
889 uint8_t transferOpFlag;
890 uint16_t attributeHandle;
891
892 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
893 request, payloadLength, &transferHandle, &transferOpFlag,
894 &attributeHandle);
895 if (rc != PLDM_SUCCESS)
896 {
897 return ccOnlyResponse(request, rc);
898 }
899
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600900 fs::path tablesPath(BIOS_TABLES_DIR);
901 auto stringTablePath = tablesPath / stringTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800902 BIOSTable biosStringTable(stringTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600903 auto attrTablePath = tablesPath / attrTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800904 BIOSTable biosAttributeTable(attrTablePath.c_str());
905 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600906 {
907 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
908 }
909
910 auto attrValueTablePath = tablesPath / attrValTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800911 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600912
John Wangf719f3b2020-01-17 08:46:22 +0800913 if (biosAttributeValueTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600914 {
915 Table attributeValueTable;
916 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800917 biosAttributeTable.load(attributeTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600918 traverseBIOSAttrTable(
919 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800920 [&biosStringTable, &attributeValueTable](
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600921 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800922 constructAttrValueTableEntry(tableEntry, biosStringTable,
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600923 attributeValueTable);
924 });
925 if (attributeValueTable.empty())
926 {
927 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
928 }
929 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800930 biosAttributeValueTable.store(attributeValueTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600931 }
John Wang8721ed62019-12-05 14:44:43 +0800932
933 Response table;
John Wangf719f3b2020-01-17 08:46:22 +0800934 biosAttributeValueTable.load(table);
John Wang8721ed62019-12-05 14:44:43 +0800935
936 auto entry = pldm_bios_table_attr_value_find_by_handle(
937 table.data(), table.size(), attributeHandle);
938 if (entry == nullptr)
939 {
940 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
941 }
942
John Wang8e877e02020-02-03 16:06:55 +0800943 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800944 Response response(sizeof(pldm_msg_hdr) +
945 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800946 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800947 0);
948 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800949 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800950 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
951 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800952 if (rc != PLDM_SUCCESS)
953 {
954 return ccOnlyResponse(request, rc);
955 }
John Wang8721ed62019-12-05 14:44:43 +0800956
957 return response;
958}
959
John Wang42174882019-12-20 14:56:59 +0800960Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
961 size_t payloadLength)
962{
963 uint32_t transferHandle;
964 uint8_t transferOpFlag;
965 variable_field attributeField;
966
967 auto rc = decode_set_bios_attribute_current_value_req(
968 request, payloadLength, &transferHandle, &transferOpFlag,
969 &attributeField);
970 if (rc != PLDM_SUCCESS)
971 {
972 return ccOnlyResponse(request, rc);
973 }
974
975 fs::path tablesPath(BIOS_TABLES_DIR);
976 auto stringTablePath = tablesPath / stringTableFile;
977 BIOSStringTable biosStringTable(stringTablePath.c_str());
978 auto attrTablePath = tablesPath / attrTableFile;
979 BIOSTable biosAttributeTable(attrTablePath.c_str());
980 auto attrValueTablePath = tablesPath / attrValTableFile;
981 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
982 // TODO: Construct attribute value table if it's empty. (another commit)
983
984 Response srcTable;
985 biosAttributeValueTable.load(srcTable);
986
987 // Replace the old attribute with the new attribute, the size of table will
988 // change:
989 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
990 // sizeof(oldAttribute) + pad(4-byte alignment, max =
991 // 3)
992 // For simplicity, we use
993 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
994 size_t destBufferLength = srcTable.size() + attributeField.length + 3;
995 Response destTable(destBufferLength);
996 size_t destTableLen = destTable.size();
997
998 rc = pldm_bios_table_attr_value_copy_and_update(
999 srcTable.data(), srcTable.size(), destTable.data(), &destTableLen,
1000 attributeField.ptr, attributeField.length);
1001 destTable.resize(destTableLen);
1002
1003 if (rc != PLDM_SUCCESS)
1004 {
1005 return ccOnlyResponse(request, rc);
1006 }
1007
1008 rc = setAttributeValueOnDbus(&attributeField, biosAttributeTable,
1009 biosStringTable);
1010 if (rc != PLDM_SUCCESS)
1011 {
1012 return ccOnlyResponse(request, rc);
1013 }
1014
1015 biosAttributeValueTable.store(destTable);
1016
1017 return ccOnlyResponse(request, PLDM_SUCCESS);
1018}
1019
Sampa Misrab37be312019-07-03 02:26:41 -05001020namespace internal
1021{
1022
1023Response buildBIOSTables(const pldm_msg* request, size_t payloadLength,
1024 const char* biosJsonDir, const char* biosTablePath)
1025{
1026 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
1027 0);
Sampa Misrab37be312019-07-03 02:26:41 -05001028
John Wange96e7e52019-10-05 17:47:30 +08001029 if (setupConfig(biosJsonDir) != 0)
1030 {
George Liufb8611d2019-12-06 10:14:15 +08001031 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wange96e7e52019-10-05 17:47:30 +08001032 }
1033
Sampa Misrab37be312019-07-03 02:26:41 -05001034 uint32_t transferHandle{};
1035 uint8_t transferOpFlag{};
1036 uint8_t tableType{};
1037
1038 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
1039 &transferOpFlag, &tableType);
George Liufb8611d2019-12-06 10:14:15 +08001040 if (rc != PLDM_SUCCESS)
Sampa Misrab37be312019-07-03 02:26:41 -05001041 {
George Liufb8611d2019-12-06 10:14:15 +08001042 return CmdHandler::ccOnlyResponse(request, rc);
1043 }
Sampa Misrab37be312019-07-03 02:26:41 -05001044
John Wangf719f3b2020-01-17 08:46:22 +08001045 BIOSTable biosStringTable(
George Liufb8611d2019-12-06 10:14:15 +08001046 (std::string(biosTablePath) + "/" + stringTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001047 BIOSTable biosAttributeTable(
George Liufb8611d2019-12-06 10:14:15 +08001048 (std::string(biosTablePath) + "/" + attrTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001049 BIOSTable biosAttributeValueTable(
George Liufb8611d2019-12-06 10:14:15 +08001050 (std::string(biosTablePath) + "/" + attrValTableFile).c_str());
1051 switch (tableType)
1052 {
1053 case PLDM_BIOS_STRING_TABLE:
Sampa Misrab37be312019-07-03 02:26:41 -05001054
John Wangf719f3b2020-01-17 08:46:22 +08001055 response = getBIOSStringTable(biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001056 break;
1057 case PLDM_BIOS_ATTR_TABLE:
1058
John Wangf719f3b2020-01-17 08:46:22 +08001059 if (biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001060 {
1061 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1062 }
1063 else
1064 {
1065 response = getBIOSAttributeTable(
John Wangf719f3b2020-01-17 08:46:22 +08001066 biosAttributeTable, biosStringTable, biosJsonDir, request);
George Liufb8611d2019-12-06 10:14:15 +08001067 }
1068 break;
1069 case PLDM_BIOS_ATTR_VAL_TABLE:
John Wangf719f3b2020-01-17 08:46:22 +08001070 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001071 {
1072 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1073 }
1074 else
1075 {
John Wangf719f3b2020-01-17 08:46:22 +08001076 response = getBIOSAttributeValueTable(biosAttributeValueTable,
1077 biosAttributeTable,
1078 biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001079 }
1080 break;
1081 default:
1082 rc = PLDM_INVALID_BIOS_TABLE_TYPE;
1083 break;
Sampa Misrab37be312019-07-03 02:26:41 -05001084 }
1085
1086 if (rc != PLDM_SUCCESS)
1087 {
George Liufb8611d2019-12-06 10:14:15 +08001088 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misrab37be312019-07-03 02:26:41 -05001089 }
1090
1091 return response;
1092}
1093
John Wangf719f3b2020-01-17 08:46:22 +08001094} // namespace internal
Sampa Misrab37be312019-07-03 02:26:41 -05001095
John Wangf719f3b2020-01-17 08:46:22 +08001096} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -06001097} // namespace responder
1098} // namespace pldm