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 { 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 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 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 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 = table::attribute::constructStringEntry(attrTable, 112 &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 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 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(sizeof(pldm_bios_attr_val_table_entry) + 164 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