1 #include "bios_table.hpp" 2 3 #include <fstream> 4 5 #include "bios_table.h" 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 20 bool BIOSTable::isEmpty() const noexcept 21 { 22 bool empty = false; 23 try 24 { 25 empty = fs::is_empty(filePath); 26 } 27 catch (fs::filesystem_error& e) 28 { 29 return true; 30 } 31 return empty; 32 } 33 34 void BIOSTable::store(const Table& table) 35 { 36 std::ofstream stream(filePath.string(), std::ios::out | std::ios::binary); 37 stream.write(reinterpret_cast<const char*>(table.data()), table.size()); 38 } 39 40 void BIOSTable::load(Response& response) const 41 { 42 auto currSize = response.size(); 43 auto fileSize = fs::file_size(filePath); 44 response.resize(currSize + fileSize); 45 std::ifstream stream(filePath.string(), std::ios::in | std::ios::binary); 46 stream.read(reinterpret_cast<char*>(response.data() + currSize), fileSize); 47 } 48 49 BIOSStringTable::BIOSStringTable(const Table& stringTable) : 50 stringTable(stringTable) 51 { 52 } 53 54 BIOSStringTable::BIOSStringTable(const BIOSTable& biosTable) 55 { 56 biosTable.load(stringTable); 57 } 58 59 std::string BIOSStringTable::findString(uint16_t handle) const 60 { 61 auto stringEntry = pldm_bios_table_string_find_by_handle( 62 stringTable.data(), stringTable.size(), handle); 63 if (stringEntry == nullptr) 64 { 65 throw std::invalid_argument("Invalid String Handle"); 66 } 67 return table::string::decodeString(stringEntry); 68 } 69 70 uint16_t BIOSStringTable::findHandle(const std::string& name) const 71 { 72 auto stringEntry = pldm_bios_table_string_find_by_string( 73 stringTable.data(), stringTable.size(), name.c_str()); 74 if (stringEntry == nullptr) 75 { 76 throw std::invalid_argument("Invalid String Name"); 77 } 78 79 return table::string::decodeHandle(stringEntry); 80 } 81 82 namespace table 83 { 84 85 void appendPadAndChecksum(Table& table) 86 { 87 auto sizeWithoutPad = table.size(); 88 auto padAndChecksumSize = pldm_bios_table_pad_checksum_size(sizeWithoutPad); 89 table.resize(table.size() + padAndChecksumSize); 90 91 pldm_bios_table_append_pad_checksum(table.data(), table.size(), 92 sizeWithoutPad); 93 } 94 95 namespace string 96 { 97 98 uint16_t decodeHandle(const pldm_bios_string_table_entry* entry) 99 { 100 return pldm_bios_table_string_entry_decode_handle(entry); 101 } 102 103 std::string decodeString(const pldm_bios_string_table_entry* entry) 104 { 105 auto strLength = pldm_bios_table_string_entry_decode_string_length(entry); 106 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */); 107 pldm_bios_table_string_entry_decode_string(entry, buffer.data(), 108 buffer.size()); 109 return std::string(buffer.data(), buffer.data() + strLength); 110 } 111 const pldm_bios_string_table_entry* constructEntry(Table& table, 112 const std::string& str) 113 { 114 auto tableSize = table.size(); 115 auto entryLength = pldm_bios_table_string_entry_encode_length(str.length()); 116 table.resize(tableSize + entryLength); 117 pldm_bios_table_string_entry_encode(table.data() + tableSize, entryLength, 118 str.c_str(), str.length()); 119 return reinterpret_cast<pldm_bios_string_table_entry*>(table.data() + 120 tableSize); 121 } 122 123 } // namespace string 124 125 namespace attribute 126 { 127 128 TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry) 129 { 130 auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry); 131 auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry); 132 auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry); 133 return {attrHandle, attrType, stringHandle}; 134 } 135 136 const pldm_bios_attr_table_entry* findByHandle(const Table& table, 137 uint16_t handle) 138 { 139 return pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 140 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 StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry) 159 { 160 auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry); 161 auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry); 162 auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry); 163 auto defLength = 164 pldm_bios_table_attr_entry_string_decode_def_string_length(entry); 165 166 std::vector<char> buffer(defLength + 1); 167 pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(), 168 buffer.size()); 169 return {strType, minLength, maxLength, defLength, 170 std::string(buffer.data(), buffer.data() + defLength)}; 171 } 172 173 } // namespace attribute 174 175 namespace attribute_value 176 { 177 178 TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry) 179 { 180 auto handle = 181 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry); 182 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry); 183 return {handle, type}; 184 } 185 186 std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry) 187 { 188 variable_field currentString{}; 189 pldm_bios_table_attr_value_entry_string_decode_string(entry, 190 ¤tString); 191 return std::string(currentString.ptr, 192 currentString.ptr + currentString.length); 193 } 194 195 const pldm_bios_attr_val_table_entry* 196 constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType, 197 const std::string& str) 198 { 199 auto strLen = str.size(); 200 auto entryLength = 201 pldm_bios_table_attr_value_entry_encode_string_length(strLen); 202 auto tableSize = table.size(); 203 table.resize(tableSize + entryLength); 204 pldm_bios_table_attr_value_entry_encode_string( 205 table.data() + tableSize, entryLength, attrHandle, attrType, strLen, 206 str.c_str()); 207 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() + 208 tableSize); 209 } 210 std::optional<Table> updateTable(const Table& table, const void* entry, 211 size_t size) 212 { 213 // Replace the old attribute with the new attribute, the size of table will 214 // change: 215 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) - 216 // sizeof(oldAttribute) + pad(4-byte alignment, max = 217 // 3) 218 // For simplicity, we use 219 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3 220 size_t destBufferLength = table.size() + size + 3; 221 Table destTable(destBufferLength); 222 223 auto rc = pldm_bios_table_attr_value_copy_and_update( 224 table.data(), table.size(), destTable.data(), &destBufferLength, entry, 225 size); 226 if (rc != PLDM_SUCCESS) 227 { 228 return std::nullopt; 229 } 230 destTable.resize(destBufferLength); 231 232 return destTable; 233 } 234 235 } // namespace attribute_value 236 237 } // namespace table 238 239 } // namespace bios 240 } // namespace responder 241 } // namespace pldm 242