1 #include "bios_string_attribute.hpp"
2
3 #include "common/utils.hpp"
4
5 #include <phosphor-logging/lg2.hpp>
6
7 #include <tuple>
8 #include <variant>
9
10 PHOSPHOR_LOG2_USING;
11
12 using namespace pldm::utils;
13
14 namespace pldm
15 {
16 namespace responder
17 {
18 namespace bios
19 {
BIOSStringAttribute(const Json & entry,DBusHandler * const dbusHandler)20 BIOSStringAttribute::BIOSStringAttribute(const Json& entry,
21 DBusHandler* const dbusHandler) :
22 BIOSAttribute(entry, dbusHandler)
23 {
24 std::string strTypeTmp = entry.at("string_type");
25 auto iter = strTypeMap.find(strTypeTmp);
26 if (iter == strTypeMap.end())
27 {
28 error("Wrong string type '{TYPE}' for attribute '{ATTRIBUTE}'", "TYPE",
29 strTypeTmp, "ATTRIBUTE", name);
30 throw std::invalid_argument("Wrong string type");
31 }
32 stringInfo.stringType = static_cast<uint8_t>(iter->second);
33
34 stringInfo.minLength = entry.at("minimum_string_length");
35 stringInfo.maxLength = entry.at("maximum_string_length");
36 stringInfo.defString = entry.at("default_string");
37 stringInfo.defLength =
38 static_cast<uint16_t>((stringInfo.defString).length());
39
40 pldm_bios_table_attr_entry_string_info info = {
41 0,
42 readOnly,
43 stringInfo.stringType,
44 stringInfo.minLength,
45 stringInfo.maxLength,
46 stringInfo.defLength,
47 stringInfo.defString.data(),
48 };
49
50 const char* errmsg;
51 auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
52 if (rc != PLDM_SUCCESS)
53 {
54 error(
55 "Wrong field for string attribute '{ATTRIBUTE}', error '{ERROR}', minimum string length '{MINIMUM_STRING_LENGTH}', maximum string length '{MAXIMUM_STRING_LENGTH}', default string length '{DEFAULT_STRING_LENGTH}' and default string '{DEFAULT_STRING}'",
56 "ATTRIBUTE", name, "ERROR", errmsg, "MINIMUM_STRING_LENGTH",
57 stringInfo.minLength, "MAXIMUM_STRING_LENGTH", stringInfo.maxLength,
58 "DEFAULT_STRING_LENGTH", stringInfo.defLength, "DEFAULT_STRING",
59 stringInfo.defString);
60 throw std::invalid_argument("Wrong field for string attribute");
61 }
62 }
63
setAttrValueOnDbus(const pldm_bios_attr_val_table_entry * attrValueEntry,const pldm_bios_attr_table_entry *,const BIOSStringTable &)64 void BIOSStringAttribute::setAttrValueOnDbus(
65 const pldm_bios_attr_val_table_entry* attrValueEntry,
66 const pldm_bios_attr_table_entry*, const BIOSStringTable&)
67 {
68 if (!dBusMap.has_value())
69 {
70 return;
71 }
72
73 PropertyValue value =
74 table::attribute_value::decodeStringEntry(attrValueEntry);
75 dbusHandler->setDbusProperty(*dBusMap, value);
76 }
77
getAttrValue()78 std::string BIOSStringAttribute::getAttrValue()
79 {
80 if (!dBusMap.has_value())
81 {
82 return stringInfo.defString;
83 }
84 try
85 {
86 return dbusHandler->getDbusProperty<std::string>(
87 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
88 dBusMap->interface.c_str());
89 }
90 catch (const std::exception& e)
91 {
92 error(
93 "Failed to get string attribute '{ATTRIBUTE}' at path '{PATH}' and interface '{INTERFACE}' for property '{PROPERTY}', error - {ERROR}",
94 "ATTRIBUTE", name, "PATH", dBusMap->objectPath, "INTERFACE",
95 dBusMap->interface, "PROPERTY", dBusMap->propertyName, "ERROR", e);
96 return stringInfo.defString;
97 }
98 }
99
constructEntry(const BIOSStringTable & stringTable,Table & attrTable,Table & attrValueTable,std::optional<std::variant<int64_t,std::string>> optAttributeValue)100 void BIOSStringAttribute::constructEntry(
101 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
102 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
103 {
104 pldm_bios_table_attr_entry_string_info info = {
105 stringTable.findHandle(name), readOnly,
106 stringInfo.stringType, stringInfo.minLength,
107 stringInfo.maxLength, stringInfo.defLength,
108 stringInfo.defString.data(),
109 };
110
111 auto attrTableEntry =
112 table::attribute::constructStringEntry(attrTable, &info);
113 auto [attrHandle, attrType,
114 _] = table::attribute::decodeHeader(attrTableEntry);
115
116 std::string currStr{};
117 if (optAttributeValue.has_value())
118 {
119 auto attributeValue = optAttributeValue.value();
120 if (attributeValue.index() == 1)
121 {
122 currStr = std::get<std::string>(attributeValue);
123 }
124 else
125 {
126 currStr = getAttrValue();
127 }
128 }
129 else
130 {
131 currStr = getAttrValue();
132 }
133
134 table::attribute_value::constructStringEntry(attrValueTable, attrHandle,
135 attrType, currStr);
136 }
137
updateAttrVal(Table & newValue,uint16_t attrHdl,uint8_t attrType,const PropertyValue & newPropVal)138 int BIOSStringAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
139 uint8_t attrType,
140 const PropertyValue& newPropVal)
141 {
142 try
143 {
144 const auto& newStringValue = std::get<std::string>(newPropVal);
145 table::attribute_value::constructStringEntry(newValue, attrHdl,
146 attrType, newStringValue);
147 }
148 catch (const std::bad_variant_access& e)
149 {
150 error("Invalid value passed for the property - {ERROR}", "ERROR", e);
151 return PLDM_ERROR;
152 }
153 return PLDM_SUCCESS;
154 }
155
generateAttributeEntry(const std::variant<int64_t,std::string> & attributevalue,Table & attrValueEntry)156 void BIOSStringAttribute::generateAttributeEntry(
157 const std::variant<int64_t, std::string>& attributevalue,
158 Table& attrValueEntry)
159 {
160 std::string value = std::get<std::string>(attributevalue);
161 uint16_t len = value.size();
162
163 attrValueEntry.resize(
164 sizeof(pldm_bios_attr_val_table_entry) + sizeof(uint16_t) + len - 1);
165
166 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
167 attrValueEntry.data());
168
169 entry->attr_type = 1;
170 memcpy(entry->value, &len, sizeof(uint16_t));
171 memcpy(entry->value + sizeof(uint16_t), value.c_str(), value.size());
172 }
173
174 } // namespace bios
175 } // namespace responder
176 } // namespace pldm
177