1 #include "bios_string_attribute.hpp" 2 3 #include "common/utils.hpp" 4 5 #include <phosphor-logging/lg2.hpp> 6 7 #include <iostream> 8 #include <tuple> 9 #include <variant> 10 11 PHOSPHOR_LOG2_USING; 12 13 using namespace pldm::utils; 14 15 namespace pldm 16 { 17 namespace responder 18 { 19 namespace bios 20 { 21 BIOSStringAttribute::BIOSStringAttribute(const Json& entry, 22 DBusHandler* const dbusHandler) : 23 BIOSAttribute(entry, dbusHandler) 24 { 25 std::string strTypeTmp = entry.at("string_type"); 26 auto iter = strTypeMap.find(strTypeTmp); 27 if (iter == strTypeMap.end()) 28 { 29 error( 30 "Wrong string type, STRING_TYPE={STR_TYPE} ATTRIBUTE_NAME={ATTR_NAME}", 31 "STR_TYP", strTypeTmp, "ATTR_NAME", name); 32 throw std::invalid_argument("Wrong string type"); 33 } 34 stringInfo.stringType = static_cast<uint8_t>(iter->second); 35 36 stringInfo.minLength = entry.at("minimum_string_length"); 37 stringInfo.maxLength = entry.at("maximum_string_length"); 38 stringInfo.defLength = entry.at("default_string_length"); 39 stringInfo.defString = entry.at("default_string"); 40 41 pldm_bios_table_attr_entry_string_info info = { 42 0, 43 readOnly, 44 stringInfo.stringType, 45 stringInfo.minLength, 46 stringInfo.maxLength, 47 stringInfo.defLength, 48 stringInfo.defString.data(), 49 }; 50 51 const char* errmsg; 52 auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg); 53 if (rc != PLDM_SUCCESS) 54 { 55 error( 56 "Wrong field for string attribute, ATTRIBUTE_NAME={ATTR_NAME} ERRMSG={ERR_MSG} MINIMUM_STRING_LENGTH={MIN_LEN} MAXIMUM_STRING_LENGTH={MAX_LEN} DEFAULT_STRING_LENGTH={DEF_LEN} DEFAULT_STRING={DEF_STR}", 57 "ATTR_NAME", name, "ERR_MSG", errmsg, "MIN_LEN", 58 stringInfo.minLength, "MAX_LEN", stringInfo.maxLength, "DEF_LEN", 59 stringInfo.defLength, "DEF_STR", 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 "Error getting string attribute '{ATTR}' from '{INTERFACE}': {ERROR}", 94 "ATTR", name, "INTERFACE", dBusMap->interface, "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: {ERR_EXCEP}", 150 "ERR_EXCEP", e.what()); 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