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.defLength = entry.at("default_string_length"); 37 stringInfo.defString = entry.at("default_string"); 38 39 pldm_bios_table_attr_entry_string_info info = { 40 0, 41 readOnly, 42 stringInfo.stringType, 43 stringInfo.minLength, 44 stringInfo.maxLength, 45 stringInfo.defLength, 46 stringInfo.defString.data(), 47 }; 48 49 const char* errmsg; 50 auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg); 51 if (rc != PLDM_SUCCESS) 52 { 53 error( 54 "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}'", 55 "ATTRIBUTE", name, "ERROR", errmsg, "MINIMUM_STRING_LENGTH", 56 stringInfo.minLength, "MAXIMUM_STRING_LENGTH", stringInfo.maxLength, 57 "DEFAULT_STRING_LENGTH", stringInfo.defLength, "DEFAULT_STRING", 58 stringInfo.defString); 59 throw std::invalid_argument("Wrong field for string attribute"); 60 } 61 } 62 63 void BIOSStringAttribute::setAttrValueOnDbus( 64 const pldm_bios_attr_val_table_entry* attrValueEntry, 65 const pldm_bios_attr_table_entry*, const BIOSStringTable&) 66 { 67 if (!dBusMap.has_value()) 68 { 69 return; 70 } 71 72 PropertyValue value = 73 table::attribute_value::decodeStringEntry(attrValueEntry); 74 dbusHandler->setDbusProperty(*dBusMap, value); 75 } 76 77 std::string BIOSStringAttribute::getAttrValue() 78 { 79 if (!dBusMap.has_value()) 80 { 81 return stringInfo.defString; 82 } 83 try 84 { 85 return dbusHandler->getDbusProperty<std::string>( 86 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(), 87 dBusMap->interface.c_str()); 88 } 89 catch (const std::exception& e) 90 { 91 error( 92 "Failed to get string attribute '{ATTRIBUTE}' at path '{PATH}' and interface '{INTERFACE}' for property '{PROPERTY}', error - {ERROR}", 93 "ATTRIBUTE", name, "PATH", dBusMap->objectPath, "INTERFACE", 94 dBusMap->interface, "PROPERTY", dBusMap->propertyName, "ERROR", e); 95 return stringInfo.defString; 96 } 97 } 98 99 void BIOSStringAttribute::constructEntry( 100 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable, 101 std::optional<std::variant<int64_t, std::string>> optAttributeValue) 102 { 103 pldm_bios_table_attr_entry_string_info info = { 104 stringTable.findHandle(name), readOnly, 105 stringInfo.stringType, stringInfo.minLength, 106 stringInfo.maxLength, stringInfo.defLength, 107 stringInfo.defString.data(), 108 }; 109 110 auto attrTableEntry = table::attribute::constructStringEntry(attrTable, 111 &info); 112 auto [attrHandle, attrType, 113 _] = table::attribute::decodeHeader(attrTableEntry); 114 115 std::string currStr{}; 116 if (optAttributeValue.has_value()) 117 { 118 auto attributeValue = optAttributeValue.value(); 119 if (attributeValue.index() == 1) 120 { 121 currStr = std::get<std::string>(attributeValue); 122 } 123 else 124 { 125 currStr = getAttrValue(); 126 } 127 } 128 else 129 { 130 currStr = getAttrValue(); 131 } 132 133 table::attribute_value::constructStringEntry(attrValueTable, attrHandle, 134 attrType, currStr); 135 } 136 137 int BIOSStringAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl, 138 uint8_t attrType, 139 const PropertyValue& newPropVal) 140 { 141 try 142 { 143 const auto& newStringValue = std::get<std::string>(newPropVal); 144 table::attribute_value::constructStringEntry(newValue, attrHdl, 145 attrType, newStringValue); 146 } 147 catch (const std::bad_variant_access& e) 148 { 149 error("Invalid value passed for the property - {ERROR}", "ERROR", e); 150 return PLDM_ERROR; 151 } 152 return PLDM_SUCCESS; 153 } 154 155 void BIOSStringAttribute::generateAttributeEntry( 156 const std::variant<int64_t, std::string>& attributevalue, 157 Table& attrValueEntry) 158 { 159 std::string value = std::get<std::string>(attributevalue); 160 uint16_t len = value.size(); 161 162 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 163 sizeof(uint16_t) + len - 1); 164 165 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>( 166 attrValueEntry.data()); 167 168 entry->attr_type = 1; 169 memcpy(entry->value, &len, sizeof(uint16_t)); 170 memcpy(entry->value + sizeof(uint16_t), value.c_str(), value.size()); 171 } 172 173 } // namespace bios 174 } // namespace responder 175 } // namespace pldm 176