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