blob: f9f3a554743a923c55adb8c5618993d68379593b [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;
George Liu1e44c732020-02-28 20:20:06 +080024using namespace pldm::utils;
Sampa Misrab37be312019-07-03 02:26:41 -050025
Deepak Kodihallid9fb1522019-11-28 10:06:34 -060026constexpr auto stringTableFile = "stringTable";
27constexpr auto attrTableFile = "attributeTable";
28constexpr auto attrValTableFile = "attributeValueTable";
29
Sampa Misra032bd502019-03-06 05:03:22 -060030namespace pldm
31{
32
Sampa Misrab37be312019-07-03 02:26:41 -050033using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Sampa Misra032bd502019-03-06 05:03:22 -060034using EpochTimeUS = uint64_t;
Sampa Misrab37be312019-07-03 02:26:41 -050035using BIOSTableRow = std::vector<uint8_t>;
Carol Wangdc220c82019-08-26 13:31:31 +080036using BIOSJsonName = std::string;
Sampa Misra032bd502019-03-06 05:03:22 -060037
38constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
Sampa Misrab37be312019-07-03 02:26:41 -050039constexpr auto padChksumMax = 7;
Sampa Misra032bd502019-03-06 05:03:22 -060040
41namespace responder
42{
43
44namespace utils
45{
46
47void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
48 uint8_t& hours, uint8_t& day, uint8_t& month,
49 uint16_t& year)
50{
51 auto t = time_t(timeSec);
52 auto time = localtime(&t);
53
George Liu83409572019-12-24 18:42:54 +080054 seconds = pldm::utils::decimalToBcd(time->tm_sec);
55 minutes = pldm::utils::decimalToBcd(time->tm_min);
56 hours = pldm::utils::decimalToBcd(time->tm_hour);
57 day = pldm::utils::decimalToBcd(time->tm_mday);
58 month = pldm::utils::decimalToBcd(time->tm_mon +
59 1); // The number of months in the range
60 // 0 to 11.PLDM expects range 1 to 12
61 year = pldm::utils::decimalToBcd(time->tm_year +
62 1900); // The number of years since 1900
Sampa Misra032bd502019-03-06 05:03:22 -060063}
64
Xiaochao Ma60227a02019-12-04 09:00:12 +080065std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
66 uint8_t day, uint8_t month, uint16_t year)
67{
68 struct std::tm stm;
69
70 stm.tm_year = year - 1900;
71 stm.tm_mon = month - 1;
72 stm.tm_mday = day;
73 stm.tm_hour = hours;
74 stm.tm_min = minutes;
75 stm.tm_sec = seconds;
76 stm.tm_isdst = -1;
77
78 // It will get the time in seconds since
79 // Epoch, 1970.1.1 00:00:00 +0000,UTC.
80 return timegm(&stm);
81}
82
John Wangc2938352019-09-30 13:58:41 +080083size_t getTableTotalsize(size_t sizeWithoutPad)
84{
John Wang79c37f12019-10-31 15:46:31 +080085 return sizeWithoutPad + pldm_bios_table_pad_checksum_size(sizeWithoutPad);
John Wangc2938352019-09-30 13:58:41 +080086}
87
88void padAndChecksum(Table& table)
89{
John Wang79c37f12019-10-31 15:46:31 +080090 auto sizeWithoutPad = table.size();
91 auto padAndChecksumSize = pldm_bios_table_pad_checksum_size(sizeWithoutPad);
92 table.resize(table.size() + padAndChecksumSize);
John Wangc2938352019-09-30 13:58:41 +080093
John Wang79c37f12019-10-31 15:46:31 +080094 pldm_bios_table_append_pad_checksum(table.data(), table.size(),
95 sizeWithoutPad);
John Wangc2938352019-09-30 13:58:41 +080096}
97
Sampa Misra032bd502019-03-06 05:03:22 -060098} // namespace utils
99
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600100namespace bios
101{
102
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600103Handler::Handler()
104{
105 try
106 {
107 fs::remove(
108 fs::path(std::string(BIOS_TABLES_DIR) + "/" + stringTableFile));
109 fs::remove(
110 fs::path(std::string(BIOS_TABLES_DIR) + "/" + attrTableFile));
111 fs::remove(
112 fs::path(std::string(BIOS_TABLES_DIR) + "/" + attrValTableFile));
113 }
114 catch (const std::exception& e)
115 {
116 }
Xiaochao Ma60227a02019-12-04 09:00:12 +0800117 handlers.emplace(PLDM_SET_DATE_TIME,
118 [this](const pldm_msg* request, size_t payloadLength) {
119 return this->setDateTime(request, payloadLength);
120 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600121 handlers.emplace(PLDM_GET_DATE_TIME,
122 [this](const pldm_msg* request, size_t payloadLength) {
123 return this->getDateTime(request, payloadLength);
124 });
125 handlers.emplace(PLDM_GET_BIOS_TABLE,
126 [this](const pldm_msg* request, size_t payloadLength) {
127 return this->getBIOSTable(request, payloadLength);
128 });
John Wang8721ed62019-12-05 14:44:43 +0800129 handlers.emplace(PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
130 [this](const pldm_msg* request, size_t payloadLength) {
131 return this->getBIOSAttributeCurrentValueByHandle(
132 request, payloadLength);
133 });
John Wang42174882019-12-20 14:56:59 +0800134 handlers.emplace(PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE,
135 [this](const pldm_msg* request, size_t payloadLength) {
136 return this->setBIOSAttributeCurrentValue(
137 request, payloadLength);
138 });
Deepak Kodihallid9fb1522019-11-28 10:06:34 -0600139}
140
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600141Response Handler::getDateTime(const pldm_msg* request, size_t /*payloadLength*/)
Sampa Misra032bd502019-03-06 05:03:22 -0600142{
143 uint8_t seconds = 0;
144 uint8_t minutes = 0;
145 uint8_t hours = 0;
146 uint8_t day = 0;
147 uint8_t month = 0;
148 uint16_t year = 0;
149
150 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
George Liu408c3c42019-10-16 16:49:15 +0800151 constexpr auto hostTimePath = "/xyz/openbmc_project/time/host";
vkaverapa6575b82019-04-03 05:33:52 -0500152 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
153 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liu782d37f2020-01-24 09:02:17 +0800154 EpochTimeUS timeUsec;
Sampa Misra032bd502019-03-06 05:03:22 -0600155
Sampa Misra032bd502019-03-06 05:03:22 -0600156 try
157 {
George Liu782d37f2020-01-24 09:02:17 +0800158 timeUsec = pldm::utils::DBusHandler().getDbusProperty<EpochTimeUS>(
159 hostTimePath, "Elapsed", timeInterface);
Sampa Misra032bd502019-03-06 05:03:22 -0600160 }
George Liu0e02c322020-01-01 09:41:51 +0800161 catch (const sdbusplus::exception::SdBusError& e)
Sampa Misra032bd502019-03-06 05:03:22 -0600162 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600163 std::cerr << "Error getting time, PATH=" << hostTimePath
164 << " TIME INTERACE=" << timeInterface << "\n";
Sampa Misra032bd502019-03-06 05:03:22 -0600165
George Liufb8611d2019-12-06 10:14:15 +0800166 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Sampa Misra032bd502019-03-06 05:03:22 -0600167 }
168
Sampa Misra032bd502019-03-06 05:03:22 -0600169 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
170 std::chrono::microseconds(timeUsec))
171 .count();
172
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600173 pldm::responder::utils::epochToBCDTime(timeSec, seconds, minutes, hours,
174 day, month, year);
Sampa Misra032bd502019-03-06 05:03:22 -0600175
George Liufb8611d2019-12-06 10:14:15 +0800176 auto rc = encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS,
177 seconds, minutes, hours, day, month,
178 year, responsePtr);
179 if (rc != PLDM_SUCCESS)
180 {
181 return ccOnlyResponse(request, rc);
182 }
183
vkaverapa6575b82019-04-03 05:33:52 -0500184 return response;
Sampa Misra032bd502019-03-06 05:03:22 -0600185}
186
Xiaochao Ma60227a02019-12-04 09:00:12 +0800187Response Handler::setDateTime(const pldm_msg* request, size_t payloadLength)
188{
189 uint8_t seconds = 0;
190 uint8_t minutes = 0;
191 uint8_t hours = 0;
192 uint8_t day = 0;
193 uint8_t month = 0;
194 uint16_t year = 0;
195 std::time_t timeSec;
196
197 constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
198 constexpr auto setTimePath = "/xyz/openbmc_project/time/host";
199 constexpr auto timeSetPro = "Elapsed";
200
201 auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
202 &minutes, &hours, &day, &month, &year);
203 if (rc != PLDM_SUCCESS)
204 {
205 return ccOnlyResponse(request, rc);
206 }
207 timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
208 month, year);
209 uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
210 std::chrono::seconds(timeSec))
211 .count();
George Liu1e44c732020-02-28 20:20:06 +0800212 PropertyValue value{timeUsec};
Xiaochao Ma60227a02019-12-04 09:00:12 +0800213 try
214 {
George Liu1e44c732020-02-28 20:20:06 +0800215 DBusMapping dbusMapping{setTimePath, setTimeInterface, timeSetPro,
216 "uint64_t"};
217 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
Xiaochao Ma60227a02019-12-04 09:00:12 +0800218 }
219 catch (std::exception& e)
220 {
221
222 std::cerr << "Error Setting time,PATH=" << setTimePath
223 << "TIME INTERFACE=" << setTimeInterface
224 << "ERROR=" << e.what() << "\n";
225
226 return ccOnlyResponse(request, PLDM_ERROR);
227 }
228
229 return ccOnlyResponse(request, PLDM_SUCCESS);
230}
231
Sampa Misrab37be312019-07-03 02:26:41 -0500232/** @brief Construct the BIOS string table
233 *
John Wangf719f3b2020-01-17 08:46:22 +0800234 * @param[in,out] biosStringTable - the string table
George Liufb8611d2019-12-06 10:14:15 +0800235 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500236 */
John Wangf719f3b2020-01-17 08:46:22 +0800237Response getBIOSStringTable(BIOSTable& biosStringTable, const pldm_msg* request)
John Wange96e7e52019-10-05 17:47:30 +0800238
Sampa Misrab37be312019-07-03 02:26:41 -0500239{
240 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
241 0);
242 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
John Wangf719f3b2020-01-17 08:46:22 +0800243 if (!biosStringTable.isEmpty())
John Wangdd9a6282019-10-11 18:52:46 +0800244 {
George Liufb8611d2019-12-06 10:14:15 +0800245 auto rc = encode_get_bios_table_resp(
246 request->hdr.instance_id, PLDM_SUCCESS,
247 0, /* next transfer handle */
248 PLDM_START_AND_END, nullptr, response.size(),
249 responsePtr); // filling up the header here
250 if (rc != PLDM_SUCCESS)
251 {
252 return CmdHandler::ccOnlyResponse(request, rc);
253 }
254
John Wangf719f3b2020-01-17 08:46:22 +0800255 biosStringTable.load(response);
John Wangdd9a6282019-10-11 18:52:46 +0800256 return response;
257 }
258 auto biosStrings = bios_parser::getStrings();
259 std::sort(biosStrings.begin(), biosStrings.end());
260 // remove all duplicate strings received from bios json
261 biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
262 biosStrings.end());
263
264 size_t sizeWithoutPad = std::accumulate(
265 biosStrings.begin(), biosStrings.end(), 0,
266 [](size_t sum, const std::string& elem) {
267 return sum +
268 pldm_bios_table_string_entry_encode_length(elem.length());
269 });
270
271 Table stringTable;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600272 stringTable.reserve(
273 pldm::responder::utils::getTableTotalsize(sizeWithoutPad));
John Wangdd9a6282019-10-11 18:52:46 +0800274
275 stringTable.resize(sizeWithoutPad);
276 auto tablePtr = stringTable.data();
277 for (const auto& elem : biosStrings)
278 {
279 auto entry_length =
280 pldm_bios_table_string_entry_encode_length(elem.length());
281 pldm_bios_table_string_entry_encode(tablePtr, sizeWithoutPad,
282 elem.c_str(), elem.length());
283 tablePtr += entry_length;
284 sizeWithoutPad -= entry_length;
Sampa Misrab37be312019-07-03 02:26:41 -0500285 }
286
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600287 pldm::responder::utils::padAndChecksum(stringTable);
John Wangf719f3b2020-01-17 08:46:22 +0800288 biosStringTable.store(stringTable);
John Wangdd9a6282019-10-11 18:52:46 +0800289 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
290 stringTable.size(),
291 0);
292 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800293 auto rc = encode_get_bios_table_resp(
294 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nxtTransferHandle */,
295 PLDM_START_AND_END, stringTable.data(), response.size(), responsePtr);
296 if (rc != PLDM_SUCCESS)
297 {
298 return CmdHandler::ccOnlyResponse(request, rc);
299 }
300
Sampa Misrab37be312019-07-03 02:26:41 -0500301 return response;
302}
303
Sampa Misrab37be312019-07-03 02:26:41 -0500304namespace bios_type_enum
305{
306
Carol Wangdc220c82019-08-26 13:31:31 +0800307using namespace bios_parser::bios_enum;
308
Sampa Misrab37be312019-07-03 02:26:41 -0500309/** @brief Find the indices into the array of the possible values of string
310 * handles for the current values.This is used in attribute value table
311 *
312 * @param[in] possiVals - vector of string handles comprising all the possible
313 * values for an attribute
314 * @param[in] currVals - vector of strings comprising all current values
315 * for an attribute
John Wangf719f3b2020-01-17 08:46:22 +0800316 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500317 *
318 * @return - std::vector<uint8_t> - indices into the array of the possible
319 * values of string handles
320 */
321std::vector<uint8_t> findStrIndices(PossibleValuesByHandle possiVals,
322 CurrentValues currVals,
John Wange297b9f2020-02-03 10:18:13 +0800323 const BIOSStringTable& biosStringTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500324{
325 std::vector<uint8_t> stringIndices;
326
327 for (const auto& currVal : currVals)
328 {
329 StringHandle curHdl;
330 try
331 {
John Wange297b9f2020-02-03 10:18:13 +0800332 curHdl = biosStringTable.findHandle(currVal);
Sampa Misrab37be312019-07-03 02:26:41 -0500333 }
John Wange297b9f2020-02-03 10:18:13 +0800334 catch (const std::exception& e)
Sampa Misrab37be312019-07-03 02:26:41 -0500335 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600336 std::cerr << "Exception fetching handle for the string, STRING="
337 << currVal.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500338 continue;
339 }
340
341 uint8_t i = 0;
342 for (auto possiHdl : possiVals)
343 {
344 if (possiHdl == curHdl)
345 {
346 stringIndices.push_back(i);
347 break;
348 }
349 i++;
350 }
351 }
352 return stringIndices;
353}
354
355/** @brief Find the indices into the array of the possible values of string
356 * handles for the default values. This is used in attribute table
357 *
358 * @param[in] possiVals - vector of strings comprising all the possible values
359 * for an attribute
360 * @param[in] defVals - vector of strings comprising all the default values
361 * for an attribute
362 * @return - std::vector<uint8_t> - indices into the array of the possible
363 * values of string
364 */
365std::vector<uint8_t> findDefaultValHandle(const PossibleValues& possiVals,
366 const DefaultValues& defVals)
367{
368 std::vector<uint8_t> defHdls;
369 for (const auto& defs : defVals)
370 {
John Wang59ef6072020-01-21 13:37:01 +0800371 auto index = std::find_if(possiVals.begin(), possiVals.end(),
372 [&defs](const auto& v) { return defs == v; });
Sampa Misrab37be312019-07-03 02:26:41 -0500373 if (index != possiVals.end())
374 {
375 defHdls.push_back(index - possiVals.begin());
376 }
377 }
378
379 return defHdls;
380}
381
382/** @brief Construct the attibute table for BIOS type Enumeration and
383 * Enumeration ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800384 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500385 * @param[in] biosJsonDir - path where the BIOS json files are present
Carol Wangdc220c82019-08-26 13:31:31 +0800386 * @param[in,out] attributeTable - the attribute table
Sampa Misrab37be312019-07-03 02:26:41 -0500387 *
Sampa Misrab37be312019-07-03 02:26:41 -0500388 */
John Wange297b9f2020-02-03 10:18:13 +0800389void constructAttrTable(const BIOSStringTable& biosStringTable,
390 Table& attributeTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500391{
Sampa Misrab37be312019-07-03 02:26:41 -0500392 const auto& attributeMap = getValues();
Sampa Misrab37be312019-07-03 02:26:41 -0500393 StringHandle strHandle;
394
395 for (const auto& [key, value] : attributeMap)
396 {
397 try
398 {
John Wange297b9f2020-02-03 10:18:13 +0800399 strHandle = biosStringTable.findHandle(key);
Sampa Misrab37be312019-07-03 02:26:41 -0500400 }
John Wange297b9f2020-02-03 10:18:13 +0800401 catch (const std::exception& e)
Sampa Misrab37be312019-07-03 02:26:41 -0500402 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600403 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
404 << key.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500405 continue;
406 }
John Wangccc04552019-10-14 14:28:25 +0800407 bool readOnly = (std::get<0>(value));
John Wang59ef6072020-01-21 13:37:01 +0800408 const PossibleValues& possiVals = std::get<1>(value);
409 const DefaultValues& defVals = std::get<2>(value);
Sampa Misrab37be312019-07-03 02:26:41 -0500410
411 std::vector<StringHandle> possiValsByHdl;
412 for (const auto& elem : possiVals)
413 {
414 try
415 {
John Wange297b9f2020-02-03 10:18:13 +0800416 auto hdl = biosStringTable.findHandle(elem);
Sampa Misrab37be312019-07-03 02:26:41 -0500417 possiValsByHdl.push_back(std::move(hdl));
418 }
John Wange297b9f2020-02-03 10:18:13 +0800419 catch (const std::exception& e)
Sampa Misrab37be312019-07-03 02:26:41 -0500420 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600421 std::cerr << "Could not find handle for BIOS string, STRING="
422 << elem.c_str() << "\n";
Sampa Misrab37be312019-07-03 02:26:41 -0500423 continue;
424 }
425 }
426 auto defValsByHdl = findDefaultValHandle(possiVals, defVals);
John Wangccc04552019-10-14 14:28:25 +0800427 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
428 possiValsByHdl.size(), defValsByHdl.size());
Sampa Misrab37be312019-07-03 02:26:41 -0500429
John Wangccc04552019-10-14 14:28:25 +0800430 auto attrTableSize = attributeTable.size();
431 attributeTable.resize(attrTableSize + entryLength, 0);
432 struct pldm_bios_table_attr_entry_enum_info info = {
433 strHandle,
434 readOnly,
435 (uint8_t)possiValsByHdl.size(),
436 possiValsByHdl.data(),
437 (uint8_t)defValsByHdl.size(),
438 defValsByHdl.data(),
439 };
440 pldm_bios_table_attr_entry_enum_encode(
441 attributeTable.data() + attrTableSize, entryLength, &info);
Sampa Misrab37be312019-07-03 02:26:41 -0500442 }
Sampa Misrab37be312019-07-03 02:26:41 -0500443}
444
John Wang3ad21752019-10-06 16:42:21 +0800445void constructAttrValueEntry(
446 const struct pldm_bios_attr_table_entry* attrTableEntry,
John Wange297b9f2020-02-03 10:18:13 +0800447 const std::string& attrName, const BIOSStringTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800448 Table& attrValueTable)
Sampa Misrab37be312019-07-03 02:26:41 -0500449{
John Wang3ad21752019-10-06 16:42:21 +0800450 CurrentValues currVals;
451 try
Sampa Misrab37be312019-07-03 02:26:41 -0500452 {
John Wang3ad21752019-10-06 16:42:21 +0800453 currVals = getAttrValue(attrName);
Sampa Misrab37be312019-07-03 02:26:41 -0500454 }
John Wang3ad21752019-10-06 16:42:21 +0800455 catch (const std::exception& e)
456 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600457 std::cerr << "getAttrValue returned error for attribute, NAME="
458 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800459 return;
460 }
461 uint8_t pv_num =
462 pldm_bios_table_attr_entry_enum_decode_pv_num(attrTableEntry);
463 PossibleValuesByHandle pvHdls(pv_num, 0);
464 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrTableEntry,
465 pvHdls.data(), pv_num);
466 std::sort(currVals.begin(), currVals.end());
467
John Wangf719f3b2020-01-17 08:46:22 +0800468 auto currValStrIndices = findStrIndices(pvHdls, currVals, biosStringTable);
John Wang3ad21752019-10-06 16:42:21 +0800469
470 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
471 currValStrIndices.size());
472 auto tableSize = attrValueTable.size();
473 attrValueTable.resize(tableSize + entryLength);
474 pldm_bios_table_attr_value_entry_encode_enum(
475 attrValueTable.data() + tableSize, entryLength,
476 attrTableEntry->attr_handle, attrTableEntry->attr_type,
477 currValStrIndices.size(), currValStrIndices.data());
Sampa Misrab37be312019-07-03 02:26:41 -0500478}
479
480} // end namespace bios_type_enum
481
Carol Wangdc220c82019-08-26 13:31:31 +0800482namespace bios_type_string
483{
Carol Wang612f35b2019-08-26 17:14:26 +0800484
485using namespace bios_parser::bios_string;
486
Carol Wangdc220c82019-08-26 13:31:31 +0800487/** @brief Construct the attibute table for BIOS type String and
488 * String ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800489 * @param[in] biosStringTable - the string table
Carol Wangdc220c82019-08-26 13:31:31 +0800490 * @param[in] biosJsonDir - path where the BIOS json files are present
491 * @param[in,out] attributeTable - the attribute table
492 *
493 */
John Wange297b9f2020-02-03 10:18:13 +0800494void constructAttrTable(const BIOSStringTable& biosStringTable,
495 Table& attributeTable)
Carol Wangdc220c82019-08-26 13:31:31 +0800496{
Carol Wang612f35b2019-08-26 17:14:26 +0800497 const auto& attributeMap = getValues();
498 StringHandle strHandle;
Carol Wang612f35b2019-08-26 17:14:26 +0800499 for (const auto& [key, value] : attributeMap)
500 {
501 try
502 {
John Wange297b9f2020-02-03 10:18:13 +0800503 strHandle = biosStringTable.findHandle(key);
Carol Wang612f35b2019-08-26 17:14:26 +0800504 }
John Wange297b9f2020-02-03 10:18:13 +0800505 catch (const std::exception& e)
Carol Wang612f35b2019-08-26 17:14:26 +0800506 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600507 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
508 << key.c_str() << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +0800509 continue;
510 }
511
John Wangccc04552019-10-14 14:28:25 +0800512 const auto& [readOnly, strType, minStrLen, maxStrLen, defaultStrLen,
Carol Wang612f35b2019-08-26 17:14:26 +0800513 defaultStr] = value;
John Wangccc04552019-10-14 14:28:25 +0800514 auto entryLength =
515 pldm_bios_table_attr_entry_string_encode_length(defaultStrLen);
Carol Wang612f35b2019-08-26 17:14:26 +0800516
John Wangccc04552019-10-14 14:28:25 +0800517 struct pldm_bios_table_attr_entry_string_info info = {
518 strHandle, readOnly, strType, minStrLen,
519 maxStrLen, defaultStrLen, defaultStr.data(),
520 };
521 auto attrTableSize = attributeTable.size();
522 attributeTable.resize(attrTableSize + entryLength, 0);
523 pldm_bios_table_attr_entry_string_encode(
524 attributeTable.data() + attrTableSize, entryLength, &info);
Carol Wang612f35b2019-08-26 17:14:26 +0800525 }
Carol Wangdc220c82019-08-26 13:31:31 +0800526}
Carol Wangb503f9e2019-09-02 16:34:10 +0800527
John Wang3ad21752019-10-06 16:42:21 +0800528void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
529 const std::string& attrName,
John Wange297b9f2020-02-03 10:18:13 +0800530 const BIOSStringTable& biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800531 Table& attrValueTable)
Carol Wangb503f9e2019-09-02 16:34:10 +0800532{
John Wangf719f3b2020-01-17 08:46:22 +0800533 std::ignore = biosStringTable;
John Wang3ad21752019-10-06 16:42:21 +0800534 std::string currStr;
535 uint16_t currStrLen = 0;
536 try
Carol Wangb503f9e2019-09-02 16:34:10 +0800537 {
John Wang3ad21752019-10-06 16:42:21 +0800538 currStr = getAttrValue(attrName);
539 currStrLen = currStr.size();
Carol Wangb503f9e2019-09-02 16:34:10 +0800540 }
John Wang3ad21752019-10-06 16:42:21 +0800541 catch (const std::exception& e)
542 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600543 std::cerr << "getAttrValue returned error for attribute, NAME="
544 << attrName.c_str() << " ERROR=" << e.what() << "\n";
John Wang3ad21752019-10-06 16:42:21 +0800545 return;
546 }
547 auto entryLength =
548 pldm_bios_table_attr_value_entry_encode_string_length(currStrLen);
549 auto tableSize = attrValueTable.size();
550 attrValueTable.resize(tableSize + entryLength);
551 pldm_bios_table_attr_value_entry_encode_string(
552 attrValueTable.data() + tableSize, entryLength,
553 attrTableEntry->attr_handle, attrTableEntry->attr_type, currStrLen,
554 currStr.c_str());
Carol Wangb503f9e2019-09-02 16:34:10 +0800555}
556
Carol Wangdc220c82019-08-26 13:31:31 +0800557} // end namespace bios_type_string
558
John Wangdbbc9ff2019-10-25 13:53:46 +0800559namespace bios_type_integer
560{
561
562using namespace bios_parser::bios_integer;
563
564/** @brief Construct the attibute table for BIOS type Integer and
565 * Integer ReadOnly
John Wangf719f3b2020-01-17 08:46:22 +0800566 * @param[in] biosStringTable - the string table
John Wangdbbc9ff2019-10-25 13:53:46 +0800567 * @param[in,out] attributeTable - the attribute table
568 *
569 */
John Wange297b9f2020-02-03 10:18:13 +0800570void constructAttrTable(const BIOSStringTable& biosStringTable,
571 Table& attributeTable)
John Wangdbbc9ff2019-10-25 13:53:46 +0800572{
573 const auto& attributeMap = getValues();
574 StringHandle strHandle;
575 for (const auto& [key, value] : attributeMap)
576 {
577 try
578 {
John Wange297b9f2020-02-03 10:18:13 +0800579 strHandle = biosStringTable.findHandle(key);
John Wangdbbc9ff2019-10-25 13:53:46 +0800580 }
John Wange297b9f2020-02-03 10:18:13 +0800581 catch (const std::exception& e)
John Wangdbbc9ff2019-10-25 13:53:46 +0800582 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600583 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
584 << key.c_str() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800585 continue;
586 }
587
588 const auto& [readOnly, lowerBound, upperBound, scalarIncrement,
589 defaultValue] = value;
590 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
591
592 struct pldm_bios_table_attr_entry_integer_info info = {
593 strHandle, readOnly, lowerBound,
594 upperBound, scalarIncrement, defaultValue,
595 };
596 auto attrTableSize = attributeTable.size();
597 attributeTable.resize(attrTableSize + entryLength, 0);
598 pldm_bios_table_attr_entry_integer_encode(
599 attributeTable.data() + attrTableSize, entryLength, &info);
600 }
601}
602
603void constructAttrValueEntry(const pldm_bios_attr_table_entry* attrTableEntry,
604 const std::string& attrName,
John Wange297b9f2020-02-03 10:18:13 +0800605 const BIOSStringTable& biosStringTable,
John Wangdbbc9ff2019-10-25 13:53:46 +0800606 Table& attrValueTable)
607{
John Wangf719f3b2020-01-17 08:46:22 +0800608 std::ignore = biosStringTable;
John Wangdbbc9ff2019-10-25 13:53:46 +0800609 uint64_t currentValue;
610 try
611 {
612 currentValue = getAttrValue(attrName);
613 }
614 catch (const std::exception& e)
615 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600616 std::cerr << "Failed to get attribute value, NAME=" << attrName.c_str()
617 << " ERROR=" << e.what() << "\n";
John Wangdbbc9ff2019-10-25 13:53:46 +0800618 return;
619 }
620 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
621 auto tableSize = attrValueTable.size();
622 attrValueTable.resize(tableSize + entryLength);
623 pldm_bios_table_attr_value_entry_encode_integer(
624 attrValueTable.data() + tableSize, entryLength,
625 attrTableEntry->attr_handle, attrTableEntry->attr_type, currentValue);
626}
627
628} // namespace bios_type_integer
629
John Wang02700402019-10-06 16:34:29 +0800630void traverseBIOSAttrTable(const Table& biosAttrTable,
631 AttrTableEntryHandler handler)
632{
633 std::unique_ptr<pldm_bios_table_iter, decltype(&pldm_bios_table_iter_free)>
634 iter(pldm_bios_table_iter_create(biosAttrTable.data(),
635 biosAttrTable.size(),
636 PLDM_BIOS_ATTR_TABLE),
637 pldm_bios_table_iter_free);
638 while (!pldm_bios_table_iter_is_end(iter.get()))
639 {
640 auto table_entry = pldm_bios_table_iter_attr_entry_value(iter.get());
641 try
642 {
643 handler(table_entry);
644 }
645 catch (const std::exception& e)
646 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600647 std::cerr << "handler fails when traversing BIOSAttrTable, ERROR="
648 << e.what() << "\n";
John Wang02700402019-10-06 16:34:29 +0800649 }
650 pldm_bios_table_iter_next(iter.get());
651 }
652}
653
John Wange297b9f2020-02-03 10:18:13 +0800654using typeHandler = std::function<void(const BIOSStringTable& biosStringTable,
John Wange96e7e52019-10-05 17:47:30 +0800655 Table& attributeTable)>;
Carol Wangdc220c82019-08-26 13:31:31 +0800656std::map<BIOSJsonName, typeHandler> attrTypeHandlers{
657 {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrTable},
John Wangdbbc9ff2019-10-25 13:53:46 +0800658 {bios_parser::bIOSStrJson, bios_type_string::constructAttrTable},
659 {bios_parser::bIOSIntegerJson, bios_type_integer::constructAttrTable},
660};
Carol Wangdc220c82019-08-26 13:31:31 +0800661
Sampa Misrab37be312019-07-03 02:26:41 -0500662/** @brief Construct the BIOS attribute table
663 *
John Wangf719f3b2020-01-17 08:46:22 +0800664 * @param[in,out] biosAttributeTable - the attribute table
665 * @param[in] biosStringTable - the string table
Sampa Misrab37be312019-07-03 02:26:41 -0500666 * @param[in] biosJsonDir - path where the BIOS json files are present
George Liufb8611d2019-12-06 10:14:15 +0800667 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500668 */
John Wangf719f3b2020-01-17 08:46:22 +0800669Response getBIOSAttributeTable(BIOSTable& biosAttributeTable,
John Wange297b9f2020-02-03 10:18:13 +0800670 const BIOSStringTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800671 const char* biosJsonDir, const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500672{
673 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
674 0);
675 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
676 uint32_t nxtTransferHandle = 0;
677 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500678
John Wangf719f3b2020-01-17 08:46:22 +0800679 if (biosAttributeTable.isEmpty())
Sampa Misrab37be312019-07-03 02:26:41 -0500680 { // no persisted table, constructing fresh table and response
Carol Wangdc220c82019-08-26 13:31:31 +0800681 Table attributeTable;
682 fs::path dir(biosJsonDir);
683
684 for (auto it = attrTypeHandlers.begin(); it != attrTypeHandlers.end();
685 it++)
686 {
687 fs::path file = dir / it->first;
688 if (fs::exists(file))
689 {
John Wangf719f3b2020-01-17 08:46:22 +0800690 it->second(biosStringTable, attributeTable);
Carol Wangdc220c82019-08-26 13:31:31 +0800691 }
692 }
693
694 if (attributeTable.empty())
695 { // no available json file is found
George Liufb8611d2019-12-06 10:14:15 +0800696 return CmdHandler::ccOnlyResponse(request,
697 PLDM_BIOS_TABLE_UNAVAILABLE);
Carol Wangdc220c82019-08-26 13:31:31 +0800698 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600699 pldm::responder::utils::padAndChecksum(attributeTable);
John Wangf719f3b2020-01-17 08:46:22 +0800700 biosAttributeTable.store(attributeTable);
Sampa Misrab37be312019-07-03 02:26:41 -0500701 response.resize(sizeof(pldm_msg_hdr) +
702 PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
703 attributeTable.size());
704 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800705
706 auto rc = encode_get_bios_table_resp(
707 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
708 transferFlag, attributeTable.data(), response.size(), responsePtr);
709 if (rc != PLDM_SUCCESS)
710 {
711 return CmdHandler::ccOnlyResponse(request, rc);
712 }
Sampa Misrab37be312019-07-03 02:26:41 -0500713 }
714 else
715 { // persisted table present, constructing response
George Liufb8611d2019-12-06 10:14:15 +0800716 auto rc = encode_get_bios_table_resp(
717 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
718 transferFlag, nullptr, response.size(),
719 responsePtr); // filling up the header here
720 if (rc != PLDM_SUCCESS)
721 {
722 return CmdHandler::ccOnlyResponse(request, rc);
723 }
John Wangf719f3b2020-01-17 08:46:22 +0800724 biosAttributeTable.load(response);
Sampa Misrab37be312019-07-03 02:26:41 -0500725 }
726
727 return response;
728}
729
John Wang3ad21752019-10-06 16:42:21 +0800730using AttrValTableEntryConstructHandler =
731 std::function<void(const struct pldm_bios_attr_table_entry* tableEntry,
732 const std::string& attrName,
John Wange297b9f2020-02-03 10:18:13 +0800733 const BIOSStringTable& biosStringTable, Table& table)>;
John Wang3ad21752019-10-06 16:42:21 +0800734
735using AttrType = uint8_t;
736const std::map<AttrType, AttrValTableEntryConstructHandler>
737 AttrValTableConstructMap{
738 {PLDM_BIOS_STRING, bios_type_string::constructAttrValueEntry},
739 {PLDM_BIOS_STRING_READ_ONLY, bios_type_string::constructAttrValueEntry},
740 {PLDM_BIOS_ENUMERATION, bios_type_enum::constructAttrValueEntry},
741 {PLDM_BIOS_ENUMERATION_READ_ONLY,
742 bios_type_enum::constructAttrValueEntry},
John Wangdbbc9ff2019-10-25 13:53:46 +0800743 {PLDM_BIOS_INTEGER, bios_type_integer::constructAttrValueEntry},
744 {PLDM_BIOS_INTEGER_READ_ONLY,
745 bios_type_integer::constructAttrValueEntry},
John Wang3ad21752019-10-06 16:42:21 +0800746 };
747
748void constructAttrValueTableEntry(
749 const struct pldm_bios_attr_table_entry* attrEntry,
John Wange297b9f2020-02-03 10:18:13 +0800750 const BIOSStringTable& biosStringTable, Table& attributeValueTable)
John Wang3ad21752019-10-06 16:42:21 +0800751{
John Wange297b9f2020-02-03 10:18:13 +0800752 auto stringHandle =
753 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
754 try
John Wang3ad21752019-10-06 16:42:21 +0800755 {
John Wange297b9f2020-02-03 10:18:13 +0800756 auto attrName = biosStringTable.findString(stringHandle);
757 AttrValTableConstructMap.at(attrEntry->attr_type)(
758 attrEntry, attrName, biosStringTable, attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800759 }
John Wange297b9f2020-02-03 10:18:13 +0800760 catch (const std::exception& e)
761 {
762 std::cerr << "constructAttrValueTableEntry Error: " << e.what()
763 << std::endl;
764 }
John Wang3ad21752019-10-06 16:42:21 +0800765}
766
Sampa Misrab37be312019-07-03 02:26:41 -0500767/** @brief Construct the BIOS attribute value table
768 *
John Wangf719f3b2020-01-17 08:46:22 +0800769 * @param[in,out] biosAttributeValueTable - the attribute value table
770 * @param[in] biosAttributeTable - the attribute table
771 * @param[in] biosStringTable - the string table
George Liufb8611d2019-12-06 10:14:15 +0800772 * @param[in] request - Request message
Sampa Misrab37be312019-07-03 02:26:41 -0500773 */
John Wangf719f3b2020-01-17 08:46:22 +0800774Response getBIOSAttributeValueTable(BIOSTable& biosAttributeValueTable,
775 const BIOSTable& biosAttributeTable,
John Wange297b9f2020-02-03 10:18:13 +0800776 const BIOSStringTable& biosStringTable,
George Liufb8611d2019-12-06 10:14:15 +0800777 const pldm_msg* request)
Sampa Misrab37be312019-07-03 02:26:41 -0500778{
779 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
780 0);
781 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
782 uint32_t nxtTransferHandle = 0;
783 uint8_t transferFlag = PLDM_START_AND_END;
Sampa Misrab37be312019-07-03 02:26:41 -0500784
John Wangf719f3b2020-01-17 08:46:22 +0800785 if (!biosAttributeValueTable.isEmpty())
John Wang3ad21752019-10-06 16:42:21 +0800786 {
George Liufb8611d2019-12-06 10:14:15 +0800787 auto rc = encode_get_bios_table_resp(
788 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle,
789 transferFlag, nullptr, response.size(),
790 responsePtr); // filling up the header here
791 if (rc != PLDM_SUCCESS)
792 {
793 return CmdHandler::ccOnlyResponse(request, rc);
794 }
795
John Wangf719f3b2020-01-17 08:46:22 +0800796 biosAttributeValueTable.load(response);
John Wang3ad21752019-10-06 16:42:21 +0800797 return response;
Sampa Misrab37be312019-07-03 02:26:41 -0500798 }
799
John Wang3ad21752019-10-06 16:42:21 +0800800 Table attributeValueTable;
801 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800802 biosAttributeTable.load(attributeTable);
John Wang3ad21752019-10-06 16:42:21 +0800803 traverseBIOSAttrTable(
804 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800805 [&biosStringTable, &attributeValueTable](
John Wang3ad21752019-10-06 16:42:21 +0800806 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800807 constructAttrValueTableEntry(tableEntry, biosStringTable,
John Wang3ad21752019-10-06 16:42:21 +0800808 attributeValueTable);
809 });
810 if (attributeValueTable.empty())
811 {
George Liufb8611d2019-12-06 10:14:15 +0800812 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wang3ad21752019-10-06 16:42:21 +0800813 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600814 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800815 biosAttributeValueTable.store(attributeValueTable);
John Wang3ad21752019-10-06 16:42:21 +0800816
817 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
818 attributeValueTable.size());
819 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800820 auto rc = encode_get_bios_table_resp(
821 request->hdr.instance_id, PLDM_SUCCESS, nxtTransferHandle, transferFlag,
822 attributeValueTable.data(), response.size(), responsePtr);
823 if (rc != PLDM_SUCCESS)
824 {
825 return CmdHandler::ccOnlyResponse(request, rc);
826 }
John Wang3ad21752019-10-06 16:42:21 +0800827
Sampa Misrab37be312019-07-03 02:26:41 -0500828 return response;
829}
830
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600831Response Handler::getBIOSTable(const pldm_msg* request, size_t payloadLength)
Sampa Misrab37be312019-07-03 02:26:41 -0500832{
Deepak Kodihallic3d20892019-08-01 05:38:31 -0500833 fs::create_directory(BIOS_TABLES_DIR);
Sampa Misrab37be312019-07-03 02:26:41 -0500834 auto response = internal::buildBIOSTables(request, payloadLength,
835 BIOS_JSONS_DIR, BIOS_TABLES_DIR);
836
837 return response;
838}
839
John Wang8721ed62019-12-05 14:44:43 +0800840Response Handler::getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
841 size_t payloadLength)
842{
843 uint32_t transferHandle;
844 uint8_t transferOpFlag;
845 uint16_t attributeHandle;
846
847 auto rc = decode_get_bios_attribute_current_value_by_handle_req(
848 request, payloadLength, &transferHandle, &transferOpFlag,
849 &attributeHandle);
850 if (rc != PLDM_SUCCESS)
851 {
852 return ccOnlyResponse(request, rc);
853 }
854
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600855 fs::path tablesPath(BIOS_TABLES_DIR);
856 auto stringTablePath = tablesPath / stringTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800857 BIOSTable biosStringTable(stringTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600858 auto attrTablePath = tablesPath / attrTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800859 BIOSTable biosAttributeTable(attrTablePath.c_str());
860 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600861 {
862 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
863 }
864
865 auto attrValueTablePath = tablesPath / attrValTableFile;
John Wangf719f3b2020-01-17 08:46:22 +0800866 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600867
John Wangf719f3b2020-01-17 08:46:22 +0800868 if (biosAttributeValueTable.isEmpty())
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600869 {
870 Table attributeValueTable;
871 Table attributeTable;
John Wangf719f3b2020-01-17 08:46:22 +0800872 biosAttributeTable.load(attributeTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600873 traverseBIOSAttrTable(
874 attributeTable,
John Wangf719f3b2020-01-17 08:46:22 +0800875 [&biosStringTable, &attributeValueTable](
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600876 const struct pldm_bios_attr_table_entry* tableEntry) {
John Wangf719f3b2020-01-17 08:46:22 +0800877 constructAttrValueTableEntry(tableEntry, biosStringTable,
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600878 attributeValueTable);
879 });
880 if (attributeValueTable.empty())
881 {
882 return ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
883 }
884 pldm::responder::utils::padAndChecksum(attributeValueTable);
John Wangf719f3b2020-01-17 08:46:22 +0800885 biosAttributeValueTable.store(attributeValueTable);
Deepak Kodihalli4976a682020-01-07 05:48:29 -0600886 }
John Wang8721ed62019-12-05 14:44:43 +0800887
888 Response table;
John Wangf719f3b2020-01-17 08:46:22 +0800889 biosAttributeValueTable.load(table);
John Wang8721ed62019-12-05 14:44:43 +0800890
891 auto entry = pldm_bios_table_attr_value_find_by_handle(
892 table.data(), table.size(), attributeHandle);
893 if (entry == nullptr)
894 {
895 return ccOnlyResponse(request, PLDM_INVALID_BIOS_ATTR_HANDLE);
896 }
897
John Wang8e877e02020-02-03 16:06:55 +0800898 auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
John Wang8721ed62019-12-05 14:44:43 +0800899 Response response(sizeof(pldm_msg_hdr) +
900 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_MIN_RESP_BYTES +
John Wang8e877e02020-02-03 16:06:55 +0800901 entryLength,
John Wang8721ed62019-12-05 14:44:43 +0800902 0);
903 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
George Liufb8611d2019-12-06 10:14:15 +0800904 rc = encode_get_bios_current_value_by_handle_resp(
John Wang8e877e02020-02-03 16:06:55 +0800905 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
906 reinterpret_cast<const uint8_t*>(entry), entryLength, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800907 if (rc != PLDM_SUCCESS)
908 {
909 return ccOnlyResponse(request, rc);
910 }
John Wang8721ed62019-12-05 14:44:43 +0800911
912 return response;
913}
914
John Wang42174882019-12-20 14:56:59 +0800915Response Handler::setBIOSAttributeCurrentValue(const pldm_msg* request,
916 size_t payloadLength)
917{
918 uint32_t transferHandle;
919 uint8_t transferOpFlag;
920 variable_field attributeField;
921
922 auto rc = decode_set_bios_attribute_current_value_req(
923 request, payloadLength, &transferHandle, &transferOpFlag,
924 &attributeField);
925 if (rc != PLDM_SUCCESS)
926 {
927 return ccOnlyResponse(request, rc);
928 }
929
930 fs::path tablesPath(BIOS_TABLES_DIR);
931 auto stringTablePath = tablesPath / stringTableFile;
932 BIOSStringTable biosStringTable(stringTablePath.c_str());
933 auto attrTablePath = tablesPath / attrTableFile;
934 BIOSTable biosAttributeTable(attrTablePath.c_str());
935 auto attrValueTablePath = tablesPath / attrValTableFile;
936 BIOSTable biosAttributeValueTable(attrValueTablePath.c_str());
937 // TODO: Construct attribute value table if it's empty. (another commit)
938
939 Response srcTable;
940 biosAttributeValueTable.load(srcTable);
941
942 // Replace the old attribute with the new attribute, the size of table will
943 // change:
944 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
945 // sizeof(oldAttribute) + pad(4-byte alignment, max =
946 // 3)
947 // For simplicity, we use
948 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
949 size_t destBufferLength = srcTable.size() + attributeField.length + 3;
950 Response destTable(destBufferLength);
951 size_t destTableLen = destTable.size();
952
953 rc = pldm_bios_table_attr_value_copy_and_update(
954 srcTable.data(), srcTable.size(), destTable.data(), &destTableLen,
955 attributeField.ptr, attributeField.length);
956 destTable.resize(destTableLen);
957
958 if (rc != PLDM_SUCCESS)
959 {
960 return ccOnlyResponse(request, rc);
961 }
962
963 rc = setAttributeValueOnDbus(&attributeField, biosAttributeTable,
964 biosStringTable);
965 if (rc != PLDM_SUCCESS)
966 {
967 return ccOnlyResponse(request, rc);
968 }
969
970 biosAttributeValueTable.store(destTable);
971
972 return ccOnlyResponse(request, PLDM_SUCCESS);
973}
974
Sampa Misrab37be312019-07-03 02:26:41 -0500975namespace internal
976{
977
978Response buildBIOSTables(const pldm_msg* request, size_t payloadLength,
979 const char* biosJsonDir, const char* biosTablePath)
980{
981 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
982 0);
Sampa Misrab37be312019-07-03 02:26:41 -0500983
John Wange96e7e52019-10-05 17:47:30 +0800984 if (setupConfig(biosJsonDir) != 0)
985 {
George Liufb8611d2019-12-06 10:14:15 +0800986 return CmdHandler::ccOnlyResponse(request, PLDM_BIOS_TABLE_UNAVAILABLE);
John Wange96e7e52019-10-05 17:47:30 +0800987 }
988
Sampa Misrab37be312019-07-03 02:26:41 -0500989 uint32_t transferHandle{};
990 uint8_t transferOpFlag{};
991 uint8_t tableType{};
992
993 auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
994 &transferOpFlag, &tableType);
George Liufb8611d2019-12-06 10:14:15 +0800995 if (rc != PLDM_SUCCESS)
Sampa Misrab37be312019-07-03 02:26:41 -0500996 {
George Liufb8611d2019-12-06 10:14:15 +0800997 return CmdHandler::ccOnlyResponse(request, rc);
998 }
Sampa Misrab37be312019-07-03 02:26:41 -0500999
John Wangf719f3b2020-01-17 08:46:22 +08001000 BIOSTable biosStringTable(
George Liufb8611d2019-12-06 10:14:15 +08001001 (std::string(biosTablePath) + "/" + stringTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001002 BIOSTable biosAttributeTable(
George Liufb8611d2019-12-06 10:14:15 +08001003 (std::string(biosTablePath) + "/" + attrTableFile).c_str());
John Wangf719f3b2020-01-17 08:46:22 +08001004 BIOSTable biosAttributeValueTable(
George Liufb8611d2019-12-06 10:14:15 +08001005 (std::string(biosTablePath) + "/" + attrValTableFile).c_str());
1006 switch (tableType)
1007 {
1008 case PLDM_BIOS_STRING_TABLE:
Sampa Misra5b145b92020-03-02 01:06:47 -06001009 {
1010 try
1011 {
1012 fs::remove(fs::path(std::string(BIOS_TABLES_DIR) + "/" +
1013 stringTableFile));
1014 fs::remove(fs::path(std::string(BIOS_TABLES_DIR) + "/" +
1015 attrTableFile));
1016 fs::remove(fs::path(std::string(BIOS_TABLES_DIR) + "/" +
1017 attrValTableFile));
1018 }
1019 catch (const std::exception& e)
1020 {
1021 }
Sampa Misrab37be312019-07-03 02:26:41 -05001022
John Wangf719f3b2020-01-17 08:46:22 +08001023 response = getBIOSStringTable(biosStringTable, request);
Sampa Misra5b145b92020-03-02 01:06:47 -06001024 }
1025 break;
George Liufb8611d2019-12-06 10:14:15 +08001026 case PLDM_BIOS_ATTR_TABLE:
1027
John Wangf719f3b2020-01-17 08:46:22 +08001028 if (biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001029 {
1030 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1031 }
1032 else
1033 {
1034 response = getBIOSAttributeTable(
John Wangf719f3b2020-01-17 08:46:22 +08001035 biosAttributeTable, biosStringTable, biosJsonDir, request);
George Liufb8611d2019-12-06 10:14:15 +08001036 }
1037 break;
1038 case PLDM_BIOS_ATTR_VAL_TABLE:
John Wangf719f3b2020-01-17 08:46:22 +08001039 if (biosAttributeTable.isEmpty() || biosStringTable.isEmpty())
George Liufb8611d2019-12-06 10:14:15 +08001040 {
1041 rc = PLDM_BIOS_TABLE_UNAVAILABLE;
1042 }
1043 else
1044 {
John Wangf719f3b2020-01-17 08:46:22 +08001045 response = getBIOSAttributeValueTable(biosAttributeValueTable,
1046 biosAttributeTable,
1047 biosStringTable, request);
George Liufb8611d2019-12-06 10:14:15 +08001048 }
1049 break;
1050 default:
1051 rc = PLDM_INVALID_BIOS_TABLE_TYPE;
1052 break;
Sampa Misrab37be312019-07-03 02:26:41 -05001053 }
1054
1055 if (rc != PLDM_SUCCESS)
1056 {
George Liufb8611d2019-12-06 10:14:15 +08001057 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misrab37be312019-07-03 02:26:41 -05001058 }
1059
1060 return response;
1061}
1062
John Wangf719f3b2020-01-17 08:46:22 +08001063} // namespace internal
Sampa Misrab37be312019-07-03 02:26:41 -05001064
John Wangf719f3b2020-01-17 08:46:22 +08001065} // namespace bios
Sampa Misra032bd502019-03-06 05:03:22 -06001066} // namespace responder
1067} // namespace pldm