xref: /openbmc/pldm/libpldmresponder/bios_table.cpp (revision d965934f04f9d9e0edd13f8bba1207fb2936712c)
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                                                           &currentString);
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