blob: 3f379cb008ab9fe4c1fa6fd26e1e1ee5bfffb343 [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
Sampa Misrab37be312019-07-03 02:26:41 -0500302namespace bios_type_enum
303{
304
Carol Wangdc220c82019-08-26 13:31:31 +0800305using namespace bios_parser::bios_enum;
306
Sampa Misrab37be312019-07-03 02:26:41 -0500307/** @brief Find the indices into the array of the possible values of string
308 * handles for the current values.This is used in attribute value table
309 *
310 * @param[in] possiVals - vector of string handles comprising all the possible
311 * values for an attribute
312 * @param[in] currVals - vector of strings comprising all current values
313 * for an attribute
John Wangf719f3b2020-01-17 08:46:22 +0800314 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500315 *
316 * @return - std::vector<uint8_t> - indices into the array of the possible
317 * values of string handles
318 */
319std::vector<uint8_t> findStrIndices(PossibleValuesByHandle possiVals,
320 CurrentValues currVals,
John Wange297b9f2020-02-03 10:18:13 +0800321 const BIOSStringTable& biosStringTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500322{
323 std::vector<uint8_t> stringIndices;
324
325 for (const auto& currVal : currVals)
326 {
327 StringHandle curHdl;
328 try
329 {
John Wange297b9f2020-02-03 10:18:13 +0800330 curHdl = biosStringTable.findHandle(currVal);
Sampa Misrab37be312019-07-03 02:26:41 -0500331 }
John Wange297b9f2020-02-03 10:18:13 +0800332 catch (const std::exception& e)
Sampa Misrab37be312019-07-03 02:26:41 -0500333 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600334 std::cerr << "Exception fetching handle for the string, STRING="
335 << currVal.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500336 continue;
337 }
338
339 uint8_t i = 0;
340 for (auto possiHdl : possiVals)
341 {
342 if (possiHdl == curHdl)
343 {
344 stringIndices.push_back(i);
345 break;
346 }
347 i++;
348 }
349 }
350 return stringIndices;
351}
352
353/** @brief Find the indices into the array of the possible values of string
354 * handles for the default values. This is used in attribute table
355 *
356 * @param[in] possiVals - vector of strings comprising all the possible values
357 * for an attribute
358 * @param[in] defVals - vector of strings comprising all the default values
359 * for an attribute
360 * @return - std::vector<uint8_t> - indices into the array of the possible
361 * values of string
362 */
363std::vector<uint8_t> findDefaultValHandle(const PossibleValues& possiVals,
364 const DefaultValues& defVals)
365{
366 std::vector<uint8_t> defHdls;
367 for (const auto& defs : defVals)
368 {
John Wang59ef6072020-01-21 13:37:01 +0800369 auto index = std::find_if(possiVals.begin(), possiVals.end(),
370 [&defs](const auto& v) { return defs == v; });
Sampa Misrab37be312019-07-03 02:26:41 -0500371 if (index != possiVals.end())
372 {
373 defHdls.push_back(index - possiVals.begin());
374 }
375 }
376
377 return defHdls;
378}
379
380/** @brief Construct the attibute table for BIOS type Enumeration and
381 * Enumeration ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800382 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500383 * @param[in] biosJsonDir - path where the BIOS json files are present
Carol Wangdc220c82019-08-26 13:31:31 +0800384 * @param[in,out] attributeTable - the attribute table
Sampa Misrab37be312019-07-03 02:26:41 -0500385 *
Sampa Misrab37be312019-07-03 02:26:41 -0500386 */
John Wange297b9f2020-02-03 10:18:13 +0800387void constructAttrTable(const BIOSStringTable& biosStringTable,
388 Table& attributeTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500389{
Sampa Misrab37be312019-07-03 02:26:41 -0500390 const auto& attributeMap = getValues();
Sampa Misrab37be312019-07-03 02:26:41 -0500391 StringHandle strHandle;
392
393 for (const auto& [key, value] : attributeMap)
394 {
395 try
396 {
John Wange297b9f2020-02-03 10:18:13 +0800397 strHandle = biosStringTable.findHandle(key);
Sampa Misrab37be312019-07-03 02:26:41 -0500398 }
John Wange297b9f2020-02-03 10:18:13 +0800399 catch (const std::exception& e)
Sampa Misrab37be312019-07-03 02:26:41 -0500400 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600401 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
402 << key.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500403 continue;
404 }
John Wangccc04552019-10-14 14:28:25 +0800405 bool readOnly = (std::get<0>(value));
John Wang59ef6072020-01-21 13:37:01 +0800406 const PossibleValues& possiVals = std::get<1>(value);
407 const DefaultValues& defVals = std::get<2>(value);
Sampa Misrab37be312019-07-03 02:26:41 -0500408
409 std::vector<StringHandle> possiValsByHdl;
410 for (const auto& elem : possiVals)
411 {
412 try
413 {
John Wange297b9f2020-02-03 10:18:13 +0800414 auto hdl = biosStringTable.findHandle(elem);
Sampa Misrab37be312019-07-03 02:26:41 -0500415 possiValsByHdl.push_back(std::move(hdl));
416 }
John Wange297b9f2020-02-03 10:18:13 +0800417 catch (const std::exception& e)
Sampa Misrab37be312019-07-03 02:26:41 -0500418 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600419 std::cerr << "Could not find handle for BIOS string, STRING="
420 << elem.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500421 continue;
422 }
423 }
424 auto defValsByHdl = findDefaultValHandle(possiVals, defVals);
John Wangccc04552019-10-14 14:28:25 +0800425 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
426 possiValsByHdl.size(), defValsByHdl.size());
Sampa Misrab37be312019-07-03 02:26:41 -0500427
John Wangccc04552019-10-14 14:28:25 +0800428 auto attrTableSize = attributeTable.size();
429 attributeTable.resize(attrTableSize + entryLength, 0);
430 struct pldm_bios_table_attr_entry_enum_info info = {
431 strHandle,
432 readOnly,
433 (uint8_t)possiValsByHdl.size(),
434 possiValsByHdl.data(),
435 (uint8_t)defValsByHdl.size(),
436 defValsByHdl.data(),
437 };
438 pldm_bios_table_attr_entry_enum_encode(
439 attributeTable.data() + attrTableSize, entryLength, &info);
Sampa Misrab37be312019-07-03 02:26:41 -0500440 }
Sampa Misrab37be312019-07-03 02:26:41 -0500441}
442
John Wang3ad21752019-10-06 16:42:21 +0800443void constructAttrValueEntry(
444 const struct pldm_bios_attr_table_entry* attrTableEntry,
John Wange297b9f2020-02-03 10:18:13 +0800445 const std::string& attrName, const BIOSStringTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800446 Table& attrValueTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500447{
John Wang3ad21752019-10-06 16:42:21 +0800448 CurrentValues currVals;
449 try
Sampa Misrab37be312019-07-03 02:26:41 -0500450 {
John Wang3ad21752019-10-06 16:42:21 +0800451 currVals = getAttrValue(attrName);
Sampa Misrab37be312019-07-03 02:26:41 -0500452 }
John Wang3ad21752019-10-06 16:42:21 +0800453 catch (const std::exception& e)
454 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600455 std::cerr << "getAttrValue returned error for attribute, NAME="
456 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800457 return;
458 }
459 uint8_t pv_num =
460 pldm_bios_table_attr_entry_enum_decode_pv_num(attrTableEntry);
461 PossibleValuesByHandle pvHdls(pv_num, 0);
462 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrTableEntry,
463 pvHdls.data(), pv_num);
464 std::sort(currVals.begin(), currVals.end());
465
John Wangf719f3b2020-01-17 08:46:22 +0800466 auto currValStrIndices = findStrIndices(pvHdls, currVals, biosStringTable);
John Wang3ad21752019-10-06 16:42:21 +0800467
468 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
469 currValStrIndices.size());
470 auto tableSize = attrValueTable.size();
471 attrValueTable.resize(tableSize + entryLength);
472 pldm_bios_table_attr_value_entry_encode_enum(
473 attrValueTable.data() + tableSize, entryLength,
474 attrTableEntry->attr_handle, attrTableEntry->attr_type,
475 currValStrIndices.size(), currValStrIndices.data());
Sampa Misrab37be312019-07-03 02:26:41 -0500476}
477
478} // end namespace bios_type_enum
479
Carol Wangdc220c82019-08-26 13:31:31 +0800480namespace bios_type_string
481{
Carol Wang612f35b2019-08-26 17:14:26 +0800482
483using namespace bios_parser::bios_string;
484
Carol Wangdc220c82019-08-26 13:31:31 +0800485/** @brief Construct the attibute table for BIOS type String and
486 * String ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800487 * @param[in] biosStringTable - the string table
Carol Wangdc220c82019-08-26 13:31:31 +0800488 * @param[in] biosJsonDir - path where the BIOS json files are present
489 * @param[in,out] attributeTable - the attribute table
490 *
491 */
John Wange297b9f2020-02-03 10:18:13 +0800492void constructAttrTable(const BIOSStringTable& biosStringTable,
493 Table& attributeTable)
Carol Wangdc220c82019-08-26 13:31:31 +0800494{
Carol Wang612f35b2019-08-26 17:14:26 +0800495 const auto& attributeMap = getValues();
496 StringHandle strHandle;
Carol Wang612f35b2019-08-26 17:14:26 +0800497 for (const auto& [key, value] : attributeMap)
498 {
499 try
500 {
John Wange297b9f2020-02-03 10:18:13 +0800501 strHandle = biosStringTable.findHandle(key);
Carol Wang612f35b2019-08-26 17:14:26 +0800502 }
John Wange297b9f2020-02-03 10:18:13 +0800503 catch (const std::exception& e)
Carol Wang612f35b2019-08-26 17:14:26 +0800504 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600505 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
506 << key.c_str() << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +0800507 continue;
508 }
509
John Wangccc04552019-10-14 14:28:25 +0800510 const auto& [readOnly, strType, minStrLen, maxStrLen, defaultStrLen,
Carol Wang612f35b2019-08-26 17:14:26 +0800511 defaultStr] = value;
John Wangccc04552019-10-14 14:28:25 +0800512 auto entryLength =
513 pldm_bios_table_attr_entry_string_encode_length(defaultStrLen);
Carol Wang612f35b2019-08-26 17:14:26 +0800514
John Wangccc04552019-10-14 14:28:25 +0800515 struct pldm_bios_table_attr_entry_string_info info = {
516 strHandle, readOnly, strType, minStrLen,
517 maxStrLen, defaultStrLen, defaultStr.data(),
518 };
519 auto attrTableSize = attributeTable.size();
520 attributeTable.resize(attrTableSize + entryLength, 0);
521 pldm_bios_table_attr_entry_string_encode(
522 attributeTable.data() + attrTableSize, entryLength, &info);
Carol Wang612f35b2019-08-26 17:14:26 +0800523 }
Carol Wangdc220c82019-08-26 13:31:31 +0800524}
Carol Wangb503f9e2019-09-02 16:34:10 +0800525
John Wang3ad21752019-10-06 16:42:21 +0800526void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
527 const std::string& attrName,
John Wange297b9f2020-02-03 10:18:13 +0800528 const BIOSStringTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800529 Table& attrValueTable)
Carol Wangb503f9e2019-09-02 16:34:10 +0800530{
John Wangf719f3b2020-01-17 08:46:22 +0800531 std::ignore = biosStringTable;
John Wang3ad21752019-10-06 16:42:21 +0800532 std::string currStr;
533 uint16_t currStrLen = 0;
534 try
Carol Wangb503f9e2019-09-02 16:34:10 +0800535 {
John Wang3ad21752019-10-06 16:42:21 +0800536 currStr = getAttrValue(attrName);
537 currStrLen = currStr.size();
Carol Wangb503f9e2019-09-02 16:34:10 +0800538 }
John Wang3ad21752019-10-06 16:42:21 +0800539 catch (const std::exception& e)
540 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600541 std::cerr << "getAttrValue returned error for attribute, NAME="
542 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800543 return;
544 }
545 auto entryLength =
546 pldm_bios_table_attr_value_entry_encode_string_length(currStrLen);
547 auto tableSize = attrValueTable.size();
548 attrValueTable.resize(tableSize + entryLength);
549 pldm_bios_table_attr_value_entry_encode_string(
550 attrValueTable.data() + tableSize, entryLength,
551 attrTableEntry->attr_handle, attrTableEntry->attr_type, currStrLen,
552 currStr.c_str());
Carol Wangb503f9e2019-09-02 16:34:10 +0800553}
554
Carol Wangdc220c82019-08-26 13:31:31 +0800555} // end namespace bios_type_string
556
John Wangdbbc9ff2019-10-25 13:53:46 +0800557namespace bios_type_integer
558{
559
560using namespace bios_parser::bios_integer;
561
562/** @brief Construct the attibute table for BIOS type Integer and
563 * Integer ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800564 * @param[in] biosStringTable - the string table
John Wangdbbc9ff2019-10-25 13:53:46 +0800565 * @param[in,out] attributeTable - the attribute table
566 *
567 */
John Wange297b9f2020-02-03 10:18:13 +0800568void constructAttrTable(const BIOSStringTable& biosStringTable,
569 Table& attributeTable)
John Wangdbbc9ff2019-10-25 13:53:46 +0800570{
571 const auto& attributeMap = getValues();
572 StringHandle strHandle;
573 for (const auto& [key, value] : attributeMap)
574 {
575 try
576 {
John Wange297b9f2020-02-03 10:18:13 +0800577 strHandle = biosStringTable.findHandle(key);
John Wangdbbc9ff2019-10-25 13:53:46 +0800578 }
John Wange297b9f2020-02-03 10:18:13 +0800579 catch (const std::exception& e)
John Wangdbbc9ff2019-10-25 13:53:46 +0800580 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600581 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
582 << key.c_str() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800583 continue;
584 }
585
586 const auto& [readOnly, lowerBound, upperBound, scalarIncrement,
587 defaultValue] = value;
588 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
589
590 struct pldm_bios_table_attr_entry_integer_info info = {
591 strHandle, readOnly, lowerBound,
592 upperBound, scalarIncrement, defaultValue,
593 };
594 auto attrTableSize = attributeTable.size();
595 attributeTable.resize(attrTableSize + entryLength, 0);
596 pldm_bios_table_attr_entry_integer_encode(
597 attributeTable.data() + attrTableSize, entryLength, &info);
598 }
599}
600
601void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
602 const std::string& attrName,
John Wange297b9f2020-02-03 10:18:13 +0800603 const BIOSStringTable& biosStringTable,
John Wangdbbc9ff2019-10-25 13:53:46 +0800604 Table& attrValueTable)
605{
John Wangf719f3b2020-01-17 08:46:22 +0800606 std::ignore = biosStringTable;
John Wangdbbc9ff2019-10-25 13:53:46 +0800607 uint64_t currentValue;
608 try
609 {
610 currentValue = getAttrValue(attrName);
611 }
612 catch (const std::exception& e)
613 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600614 std::cerr << "Failed to get attribute value, NAME=" << attrName.c_str()
615 << " ERROR=" << e.what() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800616 return;
617 }
618 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
619 auto tableSize = attrValueTable.size();
620 attrValueTable.resize(tableSize + entryLength);
621 pldm_bios_table_attr_value_entry_encode_integer(
622 attrValueTable.data() + tableSize, entryLength,
623 attrTableEntry->attr_handle, attrTableEntry->attr_type, currentValue);
624}
625
626} // namespace bios_type_integer
627
John Wang02700402019-10-06 16:34:29 +0800628void traverseBIOSAttrTable(const Table& biosAttrTable,
629 AttrTableEntryHandler handler)
630{
631 std::unique_ptr<pldm_bios_table_iter, decltype(&pldm_bios_table_iter_free)>
632 iter(pldm_bios_table_iter_create(biosAttrTable.data(),
633 biosAttrTable.size(),
634 PLDM_BIOS_ATTR_TABLE),
635 pldm_bios_table_iter_free);
636 while (!pldm_bios_table_iter_is_end(iter.get()))
637 {
638 auto table_entry = pldm_bios_table_iter_attr_entry_value(iter.get());
639 try
640 {
641 handler(table_entry);
642 }
643 catch (const std::exception& e)
644 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600645 std::cerr << "handler fails when traversing BIOSAttrTable, ERROR="
646 << e.what() << "\n";
John Wang02700402019-10-06 16:34:29 +0800647 }
648 pldm_bios_table_iter_next(iter.get());
649 }
650}
651
John Wange297b9f2020-02-03 10:18:13 +0800652using typeHandler = std::function<void(const BIOSStringTable& biosStringTable,
John Wange96e7e52019-10-05 17:47:30 +0800653 Table& attributeTable)>;
Carol Wangdc220c82019-08-26 13:31:31 +0800654std::map<BIOSJsonName, typeHandler> attrTypeHandlers{
655 {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrTable},
John Wangdbbc9ff2019-10-25 13:53:46 +0800656 {bios_parser::bIOSStrJson, bios_type_string::constructAttrTable},
657 {bios_parser::bIOSIntegerJson, bios_type_integer::constructAttrTable},
658};
Carol Wangdc220c82019-08-26 13:31:31 +0800659
Sampa Misrab37be312019-07-03 02:26:41 -0500660/** @brief Construct the BIOS attribute table
661 *
John Wangf719f3b2020-01-17 08:46:22 +0800662 * @param[in,out] biosAttributeTable - the attribute table
663 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500664 * @param[in] biosJsonDir - path where the BIOS json files are present
George Liufb8611d2019-12-06 10:14:15 +0800665 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500666 */
John Wangf719f3b2020-01-17 08:46:22 +0800667Response getBIOSAttributeTable(BIOSTable& biosAttributeTable,
John Wange297b9f2020-02-03 10:18:13 +0800668 const BIOSStringTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800669 const char* biosJsonDir, const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500670{
671 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
672 0);
673 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
674 uint32_t nxtTransferHandle = 0;
675 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500676
John Wangf719f3b2020-01-17 08:46:22 +0800677 if (biosAttributeTable.isEmpty())
Sampa Misrab37be312019-07-03 02:26:41 -0500678 { // no persisted table, constructing fresh table and response
Carol Wangdc220c82019-08-26 13:31:31 +0800679 Table attributeTable;
680 fs::path dir(biosJsonDir);
681
682 for (auto it = attrTypeHandlers.begin(); it != attrTypeHandlers.end();
683 it++)
684 {
685 fs::path file = dir / it->first;
686 if (fs::exists(file))
687 {
John Wangf719f3b2020-01-17 08:46:22 +0800688 it->second(biosStringTable, attributeTable);
Carol Wangdc220c82019-08-26 13:31:31 +0800689 }
690 }
691
692 if (attributeTable.empty())
693 { // no available json file is found
George Liufb8611d2019-12-06 10:14:15 +0800694 return CmdHandler::ccOnlyResponse(request,
695 PLDM_BIOS_TABLE_UNAVAILABLE);
Carol Wangdc220c82019-08-26 13:31:31 +0800696 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600697 pldm::responder::utils::padAndChecksum(attributeTable);
John Wangf719f3b2020-01-17 08:46:22 +0800698 biosAttributeTable.store(attributeTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500699 response.resize(sizeof(pldm_msg_hdr) +
700 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
701 attributeTable.size());
702 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800703
704 auto rc = encode_get_bios_table_resp(
705 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
706 transferFlag, attributeTable.data(), response.size(), responsePtr);
707 if (rc != PLDM_SUCCESS)
708 {
709 return CmdHandler::ccOnlyResponse(request, rc);
710 }
Sampa Misrab37be312019-07-03 02:26:41 -0500711 }
712 else
713 { // persisted table present, constructing response
George Liufb8611d2019-12-06 10:14:15 +0800714 auto rc = encode_get_bios_table_resp(
715 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
716 transferFlag, nullptr, response.size(),
717 responsePtr); // filling up the header here
718 if (rc != PLDM_SUCCESS)
719 {
720 return CmdHandler::ccOnlyResponse(request, rc);
721 }
John Wangf719f3b2020-01-17 08:46:22 +0800722 biosAttributeTable.load(response);
Sampa Misrab37be312019-07-03 02:26:41 -0500723 }
724
725 return response;
726}
727
John Wang3ad21752019-10-06 16:42:21 +0800728using AttrValTableEntryConstructHandler =
729 std::function<void(const struct pldm_bios_attr_table_entry* tableEntry,
730 const std::string& attrName,
John Wange297b9f2020-02-03 10:18:13 +0800731 const BIOSStringTable& biosStringTable, Table& table)>;
John Wang3ad21752019-10-06 16:42:21 +0800732
733using AttrType = uint8_t;
734const std::map<AttrType, AttrValTableEntryConstructHandler>
735 AttrValTableConstructMap{
736 {PLDM_BIOS_STRING, bios_type_string::constructAttrValueEntry},
737 {PLDM_BIOS_STRING_READ_ONLY, bios_type_string::constructAttrValueEntry},
738 {PLDM_BIOS_ENUMERATION, bios_type_enum::constructAttrValueEntry},
739 {PLDM_BIOS_ENUMERATION_READ_ONLY,
740 bios_type_enum::constructAttrValueEntry},
John Wangdbbc9ff2019-10-25 13:53:46 +0800741 {PLDM_BIOS_INTEGER, bios_type_integer::constructAttrValueEntry},
742 {PLDM_BIOS_INTEGER_READ_ONLY,
743 bios_type_integer::constructAttrValueEntry},
John Wang3ad21752019-10-06 16:42:21 +0800744 };
745
746void constructAttrValueTableEntry(
747 const struct pldm_bios_attr_table_entry* attrEntry,
John Wange297b9f2020-02-03 10:18:13 +0800748 const BIOSStringTable& biosStringTable, Table& attributeValueTable)
John Wang3ad21752019-10-06 16:42:21 +0800749{
John Wange297b9f2020-02-03 10:18:13 +0800750 auto stringHandle =
751 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
752 try
John Wang3ad21752019-10-06 16:42:21 +0800753 {
John Wange297b9f2020-02-03 10:18:13 +0800754 auto attrName = biosStringTable.findString(stringHandle);
755 AttrValTableConstructMap.at(attrEntry->attr_type)(
756 attrEntry, attrName, biosStringTable, attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800757 }
John Wange297b9f2020-02-03 10:18:13 +0800758 catch (const std::exception& e)
759 {
760 std::cerr << "constructAttrValueTableEntry Error: " << e.what()
761 << std::endl;
762 }
John Wang3ad21752019-10-06 16:42:21 +0800763}
764
Sampa Misrab37be312019-07-03 02:26:41 -0500765/** @brief Construct the BIOS attribute value table
766 *
John Wangf719f3b2020-01-17 08:46:22 +0800767 * @param[in,out] biosAttributeValueTable - the attribute value table
768 * @param[in] biosAttributeTable - the attribute table
769 * @param[in] biosStringTable - the string table
George Liufb8611d2019-12-06 10:14:15 +0800770 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500771 */
John Wangf719f3b2020-01-17 08:46:22 +0800772Response getBIOSAttributeValueTable(BIOSTable& biosAttributeValueTable,
773 const BIOSTable& biosAttributeTable,
John Wange297b9f2020-02-03 10:18:13 +0800774 const BIOSStringTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800775 const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500776{
777 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
778 0);
779 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
780 uint32_t nxtTransferHandle = 0;
781 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500782
John Wangf719f3b2020-01-17 08:46:22 +0800783 if (!biosAttributeValueTable.isEmpty())
John Wang3ad21752019-10-06 16:42:21 +0800784 {
George Liufb8611d2019-12-06 10:14:15 +0800785 auto rc = encode_get_bios_table_resp(
786 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
787 transferFlag, nullptr, response.size(),
788 responsePtr); // filling up the header here
789 if (rc != PLDM_SUCCESS)
790 {
791 return CmdHandler::ccOnlyResponse(request, rc);
792 }
793
John Wangf719f3b2020-01-17 08:46:22 +0800794 biosAttributeValueTable.load(response);
John Wang3ad21752019-10-06 16:42:21 +0800795 return response;
Sampa Misrab37be312019-07-03 02:26:41 -0500796 }
797
John Wang3ad21752019-10-06 16:42:21 +0800798 Table attributeValueTable;
799 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800800 biosAttributeTable.load(attributeTable);
John Wang3ad21752019-10-06 16:42:21 +0800801 traverseBIOSAttrTable(
802 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800803 [&biosStringTable, &attributeValueTable](
John Wang3ad21752019-10-06 16:42:21 +0800804 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800805 constructAttrValueTableEntry(tableEntry, biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800806 attributeValueTable);
807 });
808 if (attributeValueTable.empty())
809 {
George Liufb8611d2019-12-06 10:14:15 +0800810 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wang3ad21752019-10-06 16:42:21 +0800811 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600812 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800813 biosAttributeValueTable.store(attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800814
815 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
816 attributeValueTable.size());
817 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800818 auto rc = encode_get_bios_table_resp(
819 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle, transferFlag,
820 attributeValueTable.data(), response.size(), responsePtr);
821 if (rc != PLDM_SUCCESS)
822 {
823 return CmdHandler::ccOnlyResponse(request, rc);
824 }
John Wang3ad21752019-10-06 16:42:21 +0800825
Sampa Misrab37be312019-07-03 02:26:41 -0500826 return response;
827}
828
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600829Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500830{
Deepak Kodihallic3d20892019-08-01 05:38:31 -0500831 fs::create_directory(BIOS_TABLES_DIR);
Sampa Misrab37be312019-07-03 02:26:41 -0500832 auto response = internal::buildBIOSTables(request, payloadLength,
833 BIOS_JSONS_DIR, BIOS_TABLES_DIR);
834
835 return response;
836}
837
John Wang8721ed62019-12-05 14:44:43 +0800838Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
839 size_t payloadLength)
840{
841 uint32_t transferHandle;
842 uint8_t transferOpFlag;
843 uint16_t attributeHandle;
844
845 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
846 request, payloadLength, &transferHandle, &transferOpFlag,
847 &attributeHandle);
848 if (rc != PLDM_SUCCESS)
849 {
850 return ccOnlyResponse(request, rc);
851 }
852
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600853 fs::path tablesPath(BIOS_TABLES_DIR);
854 auto stringTablePath = tablesPath / stringTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800855 BIOSTable biosStringTable(stringTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600856 auto attrTablePath = tablesPath / attrTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800857 BIOSTable biosAttributeTable(attrTablePath.c_str());
858 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600859 {
860 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
861 }
862
863 auto attrValueTablePath = tablesPath / attrValTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800864 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600865
John Wangf719f3b2020-01-17 08:46:22 +0800866 if (biosAttributeValueTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600867 {
868 Table attributeValueTable;
869 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800870 biosAttributeTable.load(attributeTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600871 traverseBIOSAttrTable(
872 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800873 [&biosStringTable, &attributeValueTable](
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600874 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800875 constructAttrValueTableEntry(tableEntry, biosStringTable,
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600876 attributeValueTable);
877 });
878 if (attributeValueTable.empty())
879 {
880 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
881 }
882 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800883 biosAttributeValueTable.store(attributeValueTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600884 }
John Wang8721ed62019-12-05 14:44:43 +0800885
886 Response table;
John Wangf719f3b2020-01-17 08:46:22 +0800887 biosAttributeValueTable.load(table);
John Wang8721ed62019-12-05 14:44:43 +0800888
889 auto entry = pldm_bios_table_attr_value_find_by_handle(
890 table.data(), table.size(), attributeHandle);
891 if (entry == nullptr)
892 {
893 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
894 }
895
John Wang8e877e02020-02-03 16:06:55 +0800896 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800897 Response response(sizeof(pldm_msg_hdr) +
898 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800899 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800900 0);
901 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800902 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800903 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
904 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800905 if (rc != PLDM_SUCCESS)
906 {
907 return ccOnlyResponse(request, rc);
908 }
John Wang8721ed62019-12-05 14:44:43 +0800909
910 return response;
911}
912
John Wang42174882019-12-20 14:56:59 +0800913Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
914 size_t payloadLength)
915{
916 uint32_t transferHandle;
917 uint8_t transferOpFlag;
918 variable_field attributeField;
919
920 auto rc = decode_set_bios_attribute_current_value_req(
921 request, payloadLength, &transferHandle, &transferOpFlag,
922 &attributeField);
923 if (rc != PLDM_SUCCESS)
924 {
925 return ccOnlyResponse(request, rc);
926 }
927
928 fs::path tablesPath(BIOS_TABLES_DIR);
929 auto stringTablePath = tablesPath / stringTableFile;
930 BIOSStringTable biosStringTable(stringTablePath.c_str());
931 auto attrTablePath = tablesPath / attrTableFile;
932 BIOSTable biosAttributeTable(attrTablePath.c_str());
933 auto attrValueTablePath = tablesPath / attrValTableFile;
934 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
935 // TODO: Construct attribute value table if it's empty. (another commit)
936
937 Response srcTable;
938 biosAttributeValueTable.load(srcTable);
939
940 // Replace the old attribute with the new attribute, the size of table will
941 // change:
942 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
943 // sizeof(oldAttribute) + pad(4-byte alignment, max =
944 // 3)
945 // For simplicity, we use
946 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
947 size_t destBufferLength = srcTable.size() + attributeField.length + 3;
948 Response destTable(destBufferLength);
949 size_t destTableLen = destTable.size();
950
951 rc = pldm_bios_table_attr_value_copy_and_update(
952 srcTable.data(), srcTable.size(), destTable.data(), &destTableLen,
953 attributeField.ptr, attributeField.length);
954 destTable.resize(destTableLen);
955
956 if (rc != PLDM_SUCCESS)
957 {
958 return ccOnlyResponse(request, rc);
959 }
960
961 rc = setAttributeValueOnDbus(&attributeField, biosAttributeTable,
962 biosStringTable);
963 if (rc != PLDM_SUCCESS)
964 {
965 return ccOnlyResponse(request, rc);
966 }
967
968 biosAttributeValueTable.store(destTable);
969
970 return ccOnlyResponse(request, PLDM_SUCCESS);
971}
972
Sampa Misrab37be312019-07-03 02:26:41 -0500973namespace internal
974{
975
976Response buildBIOSTables(const pldm_msg* request, size_t payloadLength,
977 const char* biosJsonDir, const char* biosTablePath)
978{
979 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
980 0);
Sampa Misrab37be312019-07-03 02:26:41 -0500981
John Wange96e7e52019-10-05 17:47:30 +0800982 if (setupConfig(biosJsonDir) != 0)
983 {
George Liufb8611d2019-12-06 10:14:15 +0800984 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wange96e7e52019-10-05 17:47:30 +0800985 }
986
Sampa Misrab37be312019-07-03 02:26:41 -0500987 uint32_t transferHandle{};
988 uint8_t transferOpFlag{};
989 uint8_t tableType{};
990
991 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
992 &transferOpFlag, &tableType);
George Liufb8611d2019-12-06 10:14:15 +0800993 if (rc != PLDM_SUCCESS)
Sampa Misrab37be312019-07-03 02:26:41 -0500994 {
George Liufb8611d2019-12-06 10:14:15 +0800995 return CmdHandler::ccOnlyResponse(request, rc);
996 }
Sampa Misrab37be312019-07-03 02:26:41 -0500997
John Wangf719f3b2020-01-17 08:46:22 +0800998 BIOSTable biosStringTable(
George Liufb8611d2019-12-06 10:14:15 +0800999 (std::string(biosTablePath) + "/" + stringTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001000 BIOSTable biosAttributeTable(
George Liufb8611d2019-12-06 10:14:15 +08001001 (std::string(biosTablePath) + "/" + attrTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001002 BIOSTable biosAttributeValueTable(
George Liufb8611d2019-12-06 10:14:15 +08001003 (std::string(biosTablePath) + "/" + attrValTableFile).c_str());
1004 switch (tableType)
1005 {
1006 case PLDM_BIOS_STRING_TABLE:
Sampa Misrab37be312019-07-03 02:26:41 -05001007
John Wangf719f3b2020-01-17 08:46:22 +08001008 response = getBIOSStringTable(biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001009 break;
1010 case PLDM_BIOS_ATTR_TABLE:
1011
John Wangf719f3b2020-01-17 08:46:22 +08001012 if (biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001013 {
1014 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1015 }
1016 else
1017 {
1018 response = getBIOSAttributeTable(
John Wangf719f3b2020-01-17 08:46:22 +08001019 biosAttributeTable, biosStringTable, biosJsonDir, request);
George Liufb8611d2019-12-06 10:14:15 +08001020 }
1021 break;
1022 case PLDM_BIOS_ATTR_VAL_TABLE:
John Wangf719f3b2020-01-17 08:46:22 +08001023 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001024 {
1025 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1026 }
1027 else
1028 {
John Wangf719f3b2020-01-17 08:46:22 +08001029 response = getBIOSAttributeValueTable(biosAttributeValueTable,
1030 biosAttributeTable,
1031 biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001032 }
1033 break;
1034 default:
1035 rc = PLDM_INVALID_BIOS_TABLE_TYPE;
1036 break;
Sampa Misrab37be312019-07-03 02:26:41 -05001037 }
1038
1039 if (rc != PLDM_SUCCESS)
1040 {
George Liufb8611d2019-12-06 10:14:15 +08001041 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misrab37be312019-07-03 02:26:41 -05001042 }
1043
1044 return response;
1045}
1046
John Wangf719f3b2020-01-17 08:46:22 +08001047} // namespace internal
Sampa Misrab37be312019-07-03 02:26:41 -05001048
John Wangf719f3b2020-01-17 08:46:22 +08001049} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -06001050} // namespace responder
1051} // namespace pldm