1 #include "bios_table.hpp" 2 3 #include <libpldm/base.h> 4 #include <libpldm/bios_table.h> 5 #include <libpldm/utils.h> 6 7 #include <fstream> 8 9 namespace pldm 10 { 11 namespace responder 12 { 13 namespace bios 14 { 15 BIOSTable::BIOSTable(const char* filePath) : filePath(filePath) {} 16 17 bool BIOSTable::isEmpty() const noexcept 18 { 19 bool empty = false; 20 try 21 { 22 empty = fs::is_empty(filePath); 23 } 24 catch (const fs::filesystem_error& e) 25 { 26 return true; 27 } 28 return empty; 29 } 30 31 void BIOSTable::store(const Table& table) 32 { 33 std::ofstream stream(filePath.string(), std::ios::out | std::ios::binary); 34 stream.write(reinterpret_cast<const char*>(table.data()), table.size()); 35 } 36 37 void BIOSTable::load(Response& response) const 38 { 39 auto currSize = response.size(); 40 auto fileSize = fs::file_size(filePath); 41 response.resize(currSize + fileSize); 42 std::ifstream stream(filePath.string(), std::ios::in | std::ios::binary); 43 stream.read(reinterpret_cast<char*>(response.data() + currSize), fileSize); 44 } 45 46 BIOSStringTable::BIOSStringTable(const Table& stringTable) : 47 stringTable(stringTable) 48 {} 49 50 BIOSStringTable::BIOSStringTable(const BIOSTable& biosTable) 51 { 52 biosTable.load(stringTable); 53 } 54 55 std::string BIOSStringTable::findString(uint16_t handle) const 56 { 57 auto stringEntry = pldm_bios_table_string_find_by_handle( 58 stringTable.data(), stringTable.size(), handle); 59 if (stringEntry == nullptr) 60 { 61 throw std::invalid_argument("Invalid String Handle"); 62 } 63 return table::string::decodeString(stringEntry); 64 } 65 66 uint16_t BIOSStringTable::findHandle(const std::string& name) const 67 { 68 auto stringEntry = pldm_bios_table_string_find_by_string( 69 stringTable.data(), stringTable.size(), name.c_str()); 70 if (stringEntry == nullptr) 71 { 72 throw std::invalid_argument("Invalid String Name"); 73 } 74 75 return table::string::decodeHandle(stringEntry); 76 } 77 78 namespace table 79 { 80 void appendPadAndChecksum(Table& table) 81 { 82 auto sizeWithoutPad = table.size(); 83 auto padAndChecksumSize = pldm_bios_table_pad_checksum_size(sizeWithoutPad); 84 table.resize(table.size() + padAndChecksumSize); 85 86 pldm_bios_table_append_pad_checksum(table.data(), table.size(), 87 sizeWithoutPad); 88 } 89 90 namespace string 91 { 92 uint16_t decodeHandle(const pldm_bios_string_table_entry* entry) 93 { 94 return pldm_bios_table_string_entry_decode_handle(entry); 95 } 96 97 std::string decodeString(const pldm_bios_string_table_entry* entry) 98 { 99 auto strLength = pldm_bios_table_string_entry_decode_string_length(entry); 100 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */); 101 pldm_bios_table_string_entry_decode_string(entry, buffer.data(), 102 buffer.size()); 103 return std::string(buffer.data(), buffer.data() + strLength); 104 } 105 const pldm_bios_string_table_entry* constructEntry(Table& table, 106 const std::string& str) 107 { 108 auto tableSize = table.size(); 109 auto entryLength = pldm_bios_table_string_entry_encode_length(str.length()); 110 table.resize(tableSize + entryLength); 111 pldm_bios_table_string_entry_encode(table.data() + tableSize, entryLength, 112 str.c_str(), str.length()); 113 return reinterpret_cast<pldm_bios_string_table_entry*>(table.data() + 114 tableSize); 115 } 116 117 } // namespace string 118 119 namespace attribute 120 { 121 TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry) 122 { 123 auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry); 124 auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry); 125 auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry); 126 return {attrHandle, attrType, stringHandle}; 127 } 128 129 const pldm_bios_attr_table_entry* findByHandle(const Table& table, 130 uint16_t handle) 131 { 132 return pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 133 handle); 134 } 135 136 const pldm_bios_attr_table_entry* findByStringHandle(const Table& table, 137 uint16_t handle) 138 { 139 return pldm_bios_table_attr_find_by_string_handle(table.data(), 140 table.size(), handle); 141 } 142 143 const pldm_bios_attr_table_entry* 144 constructStringEntry(Table& table, 145 pldm_bios_table_attr_entry_string_info* info) 146 { 147 auto entryLength = 148 pldm_bios_table_attr_entry_string_encode_length(info->def_length); 149 150 auto tableSize = table.size(); 151 table.resize(tableSize + entryLength, 0); 152 pldm_bios_table_attr_entry_string_encode(table.data() + tableSize, 153 entryLength, info); 154 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() + 155 tableSize); 156 } 157 158 const pldm_bios_attr_table_entry* 159 constructIntegerEntry(Table& table, 160 pldm_bios_table_attr_entry_integer_info* info) 161 { 162 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length(); 163 auto tableSize = table.size(); 164 table.resize(tableSize + entryLength, 0); 165 pldm_bios_table_attr_entry_integer_encode(table.data() + tableSize, 166 entryLength, info); 167 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() + 168 tableSize); 169 } 170 171 StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry) 172 { 173 auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry); 174 auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry); 175 auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry); 176 auto defLength = 177 pldm_bios_table_attr_entry_string_decode_def_string_length(entry); 178 179 std::vector<char> buffer(defLength + 1); 180 pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(), 181 buffer.size()); 182 return {strType, minLength, maxLength, defLength, 183 std::string(buffer.data(), buffer.data() + defLength)}; 184 } 185 186 IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry) 187 { 188 uint64_t lower, upper, def; 189 uint32_t scalar; 190 191 pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar, 192 &def); 193 return {lower, upper, scalar, def}; 194 } 195 196 const pldm_bios_attr_table_entry* 197 constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info) 198 { 199 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length( 200 info->pv_num, info->def_num); 201 202 auto tableSize = table.size(); 203 table.resize(tableSize + entryLength, 0); 204 pldm_bios_table_attr_entry_enum_encode(table.data() + tableSize, 205 entryLength, info); 206 207 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() + 208 tableSize); 209 } 210 211 EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry) 212 { 213 uint8_t pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(entry); 214 std::vector<uint16_t> pvHdls(pvNum, 0); 215 pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHdls.data(), pvNum); 216 auto defNum = pldm_bios_table_attr_entry_enum_decode_def_num(entry); 217 std::vector<uint8_t> defIndices(defNum, 0); 218 pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(), 219 defIndices.size()); 220 return {pvHdls, defIndices}; 221 } 222 223 } // namespace attribute 224 225 namespace attribute_value 226 { 227 TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry) 228 { 229 auto handle = 230 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry); 231 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry); 232 return {handle, type}; 233 } 234 235 std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry) 236 { 237 variable_field currentString{}; 238 pldm_bios_table_attr_value_entry_string_decode_string(entry, 239 ¤tString); 240 return std::string(currentString.ptr, 241 currentString.ptr + currentString.length); 242 } 243 244 uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry) 245 { 246 return pldm_bios_table_attr_value_entry_integer_decode_cv(entry); 247 } 248 249 std::vector<uint8_t> 250 decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry) 251 { 252 auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry); 253 std::vector<uint8_t> currHdls(number, 0); 254 pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(), 255 currHdls.size()); 256 return currHdls; 257 } 258 259 const pldm_bios_attr_val_table_entry* 260 constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType, 261 const std::string& str) 262 { 263 auto strLen = str.size(); 264 auto entryLength = 265 pldm_bios_table_attr_value_entry_encode_string_length(strLen); 266 auto tableSize = table.size(); 267 table.resize(tableSize + entryLength); 268 pldm_bios_table_attr_value_entry_encode_string( 269 table.data() + tableSize, entryLength, attrHandle, attrType, strLen, 270 str.c_str()); 271 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() + 272 tableSize); 273 } 274 275 const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table, 276 uint16_t attrHandle, 277 uint8_t attrType, 278 uint64_t value) 279 { 280 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length(); 281 282 auto tableSize = table.size(); 283 table.resize(tableSize + entryLength); 284 pldm_bios_table_attr_value_entry_encode_integer( 285 table.data() + tableSize, entryLength, attrHandle, attrType, value); 286 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() + 287 tableSize); 288 } 289 290 const pldm_bios_attr_val_table_entry* 291 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType, 292 const std::vector<uint8_t>& handleIndices) 293 { 294 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length( 295 handleIndices.size()); 296 auto tableSize = table.size(); 297 table.resize(tableSize + entryLength); 298 pldm_bios_table_attr_value_entry_encode_enum( 299 table.data() + tableSize, entryLength, attrHandle, attrType, 300 handleIndices.size(), handleIndices.data()); 301 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() + 302 tableSize); 303 } 304 305 std::optional<Table> updateTable(const Table& table, const void* entry, 306 size_t size) 307 { 308 // Replace the old attribute with the new attribute, the size of table will 309 // change: 310 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) - 311 // sizeof(oldAttribute) + pad(4-byte alignment, max = 312 // 3) 313 // For simplicity, we use 314 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3 315 size_t destBufferLength = table.size() + size + 3; 316 Table destTable(destBufferLength); 317 318 auto rc = pldm_bios_table_attr_value_copy_and_update( 319 table.data(), table.size(), destTable.data(), &destBufferLength, entry, 320 size); 321 if (rc != PLDM_SUCCESS) 322 { 323 return std::nullopt; 324 } 325 destTable.resize(destBufferLength); 326 327 return destTable; 328 } 329 330 } // namespace attribute_value 331 332 } // namespace table 333 334 } // namespace bios 335 } // namespace responder 336 } // namespace pldm 337