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