| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 1 | #include "dbus_interface.hpp" | 
|  | 2 |  | 
|  | 3 | #include "perform_probe.hpp" | 
| Christopher Meis | 59ef1e7 | 2025-04-16 08:53:25 +0200 | [diff] [blame] | 4 | #include "utils.hpp" | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 5 |  | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 6 | #include <boost/container/flat_map.hpp> | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 7 | #include <phosphor-logging/lg2.hpp> | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 8 |  | 
| Christopher Meis | 59ef1e7 | 2025-04-16 08:53:25 +0200 | [diff] [blame] | 9 | #include <fstream> | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 10 | #include <regex> | 
|  | 11 | #include <string> | 
|  | 12 | #include <vector> | 
|  | 13 |  | 
|  | 14 | using JsonVariantType = | 
|  | 15 | std::variant<std::vector<std::string>, std::vector<double>, std::string, | 
|  | 16 | int64_t, uint64_t, double, int32_t, uint32_t, int16_t, | 
|  | 17 | uint16_t, uint8_t, bool>; | 
|  | 18 |  | 
|  | 19 | namespace dbus_interface | 
|  | 20 | { | 
|  | 21 |  | 
|  | 22 | const std::regex illegalDbusPathRegex("[^A-Za-z0-9_.]"); | 
|  | 23 | const std::regex illegalDbusMemberRegex("[^A-Za-z0-9_]"); | 
|  | 24 |  | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 25 | EMDBusInterface::EMDBusInterface(boost::asio::io_context& io, | 
|  | 26 | sdbusplus::asio::object_server& objServer) : | 
|  | 27 | io(io), objServer(objServer) | 
|  | 28 | {} | 
|  | 29 |  | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 30 | void tryIfaceInitialize(std::shared_ptr<sdbusplus::asio::dbus_interface>& iface) | 
|  | 31 | { | 
|  | 32 | try | 
|  | 33 | { | 
|  | 34 | iface->initialize(); | 
|  | 35 | } | 
|  | 36 | catch (std::exception& e) | 
|  | 37 | { | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 38 | lg2::error( | 
|  | 39 | "Unable to initialize dbus interface : {ERR} object Path : {PATH} interface name : {INTF}", | 
|  | 40 | "ERR", e, "PATH", iface->get_object_path(), "INTF", | 
|  | 41 | iface->get_interface_name()); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 42 | } | 
|  | 43 | } | 
|  | 44 |  | 
| Alexander Hansen | 57604ed | 2025-06-27 13:22:28 +0200 | [diff] [blame] | 45 | std::shared_ptr<sdbusplus::asio::dbus_interface> | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 46 | EMDBusInterface::createInterface(const std::string& path, | 
|  | 47 | const std::string& interface, | 
|  | 48 | const std::string& parent, bool checkNull) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 49 | { | 
|  | 50 | // on first add we have no reason to check for null before add, as there | 
|  | 51 | // won't be any. For dynamically added interfaces, we check for null so that | 
|  | 52 | // a constant delete/add will not create a memory leak | 
|  | 53 |  | 
|  | 54 | auto ptr = objServer.add_interface(path, interface); | 
|  | 55 | auto& dataVector = inventory[parent]; | 
|  | 56 | if (checkNull) | 
|  | 57 | { | 
|  | 58 | auto it = std::find_if(dataVector.begin(), dataVector.end(), | 
|  | 59 | [](const auto& p) { return p.expired(); }); | 
|  | 60 | if (it != dataVector.end()) | 
|  | 61 | { | 
|  | 62 | *it = ptr; | 
|  | 63 | return ptr; | 
|  | 64 | } | 
|  | 65 | } | 
|  | 66 | dataVector.emplace_back(ptr); | 
|  | 67 | return ptr; | 
|  | 68 | } | 
|  | 69 |  | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 70 | void EMDBusInterface::createDeleteObjectMethod( | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 71 | const std::string& jsonPointerPath, | 
|  | 72 | const std::shared_ptr<sdbusplus::asio::dbus_interface>& iface, | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 73 | nlohmann::json& systemConfiguration) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 74 | { | 
|  | 75 | std::weak_ptr<sdbusplus::asio::dbus_interface> interface = iface; | 
|  | 76 | iface->register_method( | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 77 | "Delete", [this, &systemConfiguration, interface, | 
|  | 78 | jsonPointerPath{std::string(jsonPointerPath)}]() { | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 79 | std::shared_ptr<sdbusplus::asio::dbus_interface> dbusInterface = | 
|  | 80 | interface.lock(); | 
|  | 81 | if (!dbusInterface) | 
|  | 82 | { | 
|  | 83 | // this technically can't happen as the pointer is pointing to | 
|  | 84 | // us | 
|  | 85 | throw DBusInternalError(); | 
|  | 86 | } | 
|  | 87 | nlohmann::json::json_pointer ptr(jsonPointerPath); | 
|  | 88 | systemConfiguration[ptr] = nullptr; | 
|  | 89 |  | 
|  | 90 | // todo(james): dig through sdbusplus to find out why we can't | 
|  | 91 | // delete it in a method call | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 92 | boost::asio::post(io, [dbusInterface, this]() mutable { | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 93 | objServer.remove_interface(dbusInterface); | 
|  | 94 | }); | 
|  | 95 |  | 
| Christopher Meis | f725257 | 2025-06-11 13:22:05 +0200 | [diff] [blame] | 96 | if (!writeJsonFiles(systemConfiguration)) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 97 | { | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 98 | lg2::error("error setting json file"); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 99 | throw DBusInternalError(); | 
|  | 100 | } | 
|  | 101 | }); | 
|  | 102 | } | 
|  | 103 |  | 
| Alexander Hansen | d72dc33 | 2025-06-10 10:49:24 +0200 | [diff] [blame] | 104 | static bool checkArrayElementsSameType(nlohmann::json& value) | 
|  | 105 | { | 
|  | 106 | nlohmann::json::array_t* arr = value.get_ptr<nlohmann::json::array_t*>(); | 
|  | 107 | if (arr == nullptr) | 
|  | 108 | { | 
|  | 109 | return false; | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | if (arr->empty()) | 
|  | 113 | { | 
|  | 114 | return true; | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | nlohmann::json::value_t firstType = value[0].type(); | 
|  | 118 | return std::ranges::all_of(value, [firstType](const nlohmann::json& el) { | 
|  | 119 | return el.type() == firstType; | 
|  | 120 | }); | 
|  | 121 | } | 
|  | 122 |  | 
| Alexander Hansen | 91e360e | 2025-06-10 12:21:30 +0200 | [diff] [blame] | 123 | static nlohmann::json::value_t getDBusType( | 
|  | 124 | const nlohmann::json& value, nlohmann::json::value_t type, | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 125 | sdbusplus::asio::PropertyPermission permission) | 
|  | 126 | { | 
|  | 127 | const bool array = value.type() == nlohmann::json::value_t::array; | 
|  | 128 |  | 
|  | 129 | if (permission == sdbusplus::asio::PropertyPermission::readWrite) | 
|  | 130 | { | 
|  | 131 | // all setable numbers are doubles as it is difficult to always | 
|  | 132 | // create a configuration file with all whole numbers as decimals | 
|  | 133 | // i.e. 1.0 | 
|  | 134 | if (array) | 
|  | 135 | { | 
|  | 136 | if (value[0].is_number()) | 
|  | 137 | { | 
| Alexander Hansen | 91e360e | 2025-06-10 12:21:30 +0200 | [diff] [blame] | 138 | return nlohmann::json::value_t::number_float; | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 139 | } | 
|  | 140 | } | 
|  | 141 | else if (value.is_number()) | 
|  | 142 | { | 
| Alexander Hansen | 91e360e | 2025-06-10 12:21:30 +0200 | [diff] [blame] | 143 | return nlohmann::json::value_t::number_float; | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 144 | } | 
|  | 145 | } | 
|  | 146 |  | 
| Alexander Hansen | 91e360e | 2025-06-10 12:21:30 +0200 | [diff] [blame] | 147 | return type; | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | static void populateInterfacePropertyFromJson( | 
|  | 151 | nlohmann::json& systemConfiguration, const std::string& path, | 
|  | 152 | const nlohmann::json& key, const nlohmann::json& value, | 
|  | 153 | nlohmann::json::value_t type, | 
|  | 154 | std::shared_ptr<sdbusplus::asio::dbus_interface>& iface, | 
|  | 155 | sdbusplus::asio::PropertyPermission permission) | 
|  | 156 | { | 
|  | 157 | const auto modifiedType = getDBusType(value, type, permission); | 
|  | 158 |  | 
|  | 159 | switch (modifiedType) | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 160 | { | 
|  | 161 | case (nlohmann::json::value_t::boolean): | 
|  | 162 | { | 
| Alexander Hansen | 5531eea | 2025-08-22 11:03:09 +0200 | [diff] [blame] | 163 | addValueToDBus<bool>(key, value, *iface, permission, | 
|  | 164 | systemConfiguration, path); | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 165 | break; | 
|  | 166 | } | 
|  | 167 | case (nlohmann::json::value_t::number_integer): | 
|  | 168 | { | 
|  | 169 | addValueToDBus<int64_t>(key, value, *iface, permission, | 
|  | 170 | systemConfiguration, path); | 
|  | 171 | break; | 
|  | 172 | } | 
|  | 173 | case (nlohmann::json::value_t::number_unsigned): | 
|  | 174 | { | 
|  | 175 | addValueToDBus<uint64_t>(key, value, *iface, permission, | 
|  | 176 | systemConfiguration, path); | 
|  | 177 | break; | 
|  | 178 | } | 
|  | 179 | case (nlohmann::json::value_t::number_float): | 
|  | 180 | { | 
|  | 181 | addValueToDBus<double>(key, value, *iface, permission, | 
|  | 182 | systemConfiguration, path); | 
|  | 183 | break; | 
|  | 184 | } | 
|  | 185 | case (nlohmann::json::value_t::string): | 
|  | 186 | { | 
|  | 187 | addValueToDBus<std::string>(key, value, *iface, permission, | 
|  | 188 | systemConfiguration, path); | 
|  | 189 | break; | 
|  | 190 | } | 
|  | 191 | default: | 
|  | 192 | { | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 193 | lg2::error( | 
|  | 194 | "Unexpected json type in system configuration {KEY}: {VALUE}", | 
|  | 195 | "KEY", key, "VALUE", value.type_name()); | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 196 | break; | 
|  | 197 | } | 
|  | 198 | } | 
|  | 199 | } | 
|  | 200 |  | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 201 | // adds simple json types to interface's properties | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 202 | void EMDBusInterface::populateInterfaceFromJson( | 
|  | 203 | nlohmann::json& systemConfiguration, const std::string& jsonPointerPath, | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 204 | std::shared_ptr<sdbusplus::asio::dbus_interface>& iface, | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 205 | nlohmann::json& dict, sdbusplus::asio::PropertyPermission permission) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 206 | { | 
|  | 207 | for (const auto& [key, value] : dict.items()) | 
|  | 208 | { | 
|  | 209 | auto type = value.type(); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 210 | if (value.type() == nlohmann::json::value_t::array) | 
|  | 211 | { | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 212 | if (value.empty()) | 
|  | 213 | { | 
|  | 214 | continue; | 
|  | 215 | } | 
|  | 216 | type = value[0].type(); | 
| Alexander Hansen | d72dc33 | 2025-06-10 10:49:24 +0200 | [diff] [blame] | 217 | if (!checkArrayElementsSameType(value)) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 218 | { | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 219 | lg2::error("dbus format error {VALUE}", "VALUE", value); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 220 | continue; | 
|  | 221 | } | 
|  | 222 | } | 
|  | 223 | if (type == nlohmann::json::value_t::object) | 
|  | 224 | { | 
|  | 225 | continue; // handled elsewhere | 
|  | 226 | } | 
|  | 227 |  | 
|  | 228 | std::string path = jsonPointerPath; | 
|  | 229 | path.append("/").append(key); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 230 |  | 
| Alexander Hansen | 17f8e6a | 2025-06-10 12:10:09 +0200 | [diff] [blame] | 231 | populateInterfacePropertyFromJson(systemConfiguration, path, key, value, | 
|  | 232 | type, iface, permission); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 233 | } | 
|  | 234 | if (permission == sdbusplus::asio::PropertyPermission::readWrite) | 
|  | 235 | { | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 236 | createDeleteObjectMethod(jsonPointerPath, iface, systemConfiguration); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 237 | } | 
|  | 238 | tryIfaceInitialize(iface); | 
|  | 239 | } | 
|  | 240 |  | 
| Alexander Hansen | 57604ed | 2025-06-27 13:22:28 +0200 | [diff] [blame] | 241 | void EMDBusInterface::createAddObjectMethod( | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 242 | const std::string& jsonPointerPath, const std::string& path, | 
|  | 243 | nlohmann::json& systemConfiguration, const std::string& board) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 244 | { | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 245 | std::shared_ptr<sdbusplus::asio::dbus_interface> iface = | 
|  | 246 | createInterface(path, "xyz.openbmc_project.AddObject", board); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 247 |  | 
|  | 248 | iface->register_method( | 
|  | 249 | "AddObject", | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 250 | [&systemConfiguration, jsonPointerPath{std::string(jsonPointerPath)}, | 
|  | 251 | path{std::string(path)}, board, | 
| Alexander Hansen | 57604ed | 2025-06-27 13:22:28 +0200 | [diff] [blame] | 252 | this](const boost::container::flat_map<std::string, JsonVariantType>& | 
|  | 253 | data) { | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 254 | nlohmann::json::json_pointer ptr(jsonPointerPath); | 
|  | 255 | nlohmann::json& base = systemConfiguration[ptr]; | 
|  | 256 | auto findExposes = base.find("Exposes"); | 
|  | 257 |  | 
|  | 258 | if (findExposes == base.end()) | 
|  | 259 | { | 
|  | 260 | throw std::invalid_argument("Entity must have children."); | 
|  | 261 | } | 
|  | 262 |  | 
|  | 263 | // this will throw invalid-argument to sdbusplus if invalid json | 
|  | 264 | nlohmann::json newData{}; | 
|  | 265 | for (const auto& item : data) | 
|  | 266 | { | 
|  | 267 | nlohmann::json& newJson = newData[item.first]; | 
|  | 268 | std::visit( | 
|  | 269 | [&newJson](auto&& val) { | 
|  | 270 | newJson = std::forward<decltype(val)>(val); | 
|  | 271 | }, | 
|  | 272 | item.second); | 
|  | 273 | } | 
|  | 274 |  | 
|  | 275 | auto findName = newData.find("Name"); | 
|  | 276 | auto findType = newData.find("Type"); | 
|  | 277 | if (findName == newData.end() || findType == newData.end()) | 
|  | 278 | { | 
|  | 279 | throw std::invalid_argument("AddObject missing Name or Type"); | 
|  | 280 | } | 
|  | 281 | const std::string* type = findType->get_ptr<const std::string*>(); | 
|  | 282 | const std::string* name = findName->get_ptr<const std::string*>(); | 
|  | 283 | if (type == nullptr || name == nullptr) | 
|  | 284 | { | 
|  | 285 | throw std::invalid_argument("Type and Name must be a string."); | 
|  | 286 | } | 
|  | 287 |  | 
|  | 288 | bool foundNull = false; | 
|  | 289 | size_t lastIndex = 0; | 
|  | 290 | // we add in the "exposes" | 
|  | 291 | for (const auto& expose : *findExposes) | 
|  | 292 | { | 
|  | 293 | if (expose.is_null()) | 
|  | 294 | { | 
|  | 295 | foundNull = true; | 
|  | 296 | continue; | 
|  | 297 | } | 
|  | 298 |  | 
|  | 299 | if (expose["Name"] == *name && expose["Type"] == *type) | 
|  | 300 | { | 
|  | 301 | throw std::invalid_argument( | 
|  | 302 | "Field already in JSON, not adding"); | 
|  | 303 | } | 
|  | 304 |  | 
|  | 305 | if (foundNull) | 
|  | 306 | { | 
|  | 307 | continue; | 
|  | 308 | } | 
|  | 309 |  | 
|  | 310 | lastIndex++; | 
|  | 311 | } | 
|  | 312 |  | 
| Marc Olberding | d10dd46 | 2025-08-22 11:58:46 -0700 | [diff] [blame] | 313 | if constexpr (ENABLE_RUNTIME_VALIDATE_JSON) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 314 | { | 
| Marc Olberding | d10dd46 | 2025-08-22 11:58:46 -0700 | [diff] [blame] | 315 | const std::filesystem::path schemaPath = | 
|  | 316 | std::filesystem::path(schemaDirectory) / | 
|  | 317 | "exposes_record.json"; | 
|  | 318 |  | 
|  | 319 | std::ifstream schemaFile{schemaPath}; | 
|  | 320 |  | 
|  | 321 | if (!schemaFile.good()) | 
|  | 322 | { | 
|  | 323 | throw std::invalid_argument( | 
|  | 324 | "No schema avaliable, cannot validate."); | 
|  | 325 | } | 
|  | 326 | nlohmann::json schema = | 
|  | 327 | nlohmann::json::parse(schemaFile, nullptr, false, true); | 
|  | 328 | if (schema.is_discarded()) | 
|  | 329 | { | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 330 | lg2::error("Schema not legal: {TYPE}.json", "TYPE", *type); | 
| Marc Olberding | d10dd46 | 2025-08-22 11:58:46 -0700 | [diff] [blame] | 331 | throw DBusInternalError(); | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | if (!validateJson(schema, newData)) | 
|  | 335 | { | 
|  | 336 | throw std::invalid_argument("Data does not match schema"); | 
|  | 337 | } | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 338 | } | 
| Marc Olberding | d10dd46 | 2025-08-22 11:58:46 -0700 | [diff] [blame] | 339 |  | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 340 | if (foundNull) | 
|  | 341 | { | 
|  | 342 | findExposes->at(lastIndex) = newData; | 
|  | 343 | } | 
|  | 344 | else | 
|  | 345 | { | 
|  | 346 | findExposes->push_back(newData); | 
|  | 347 | } | 
| Christopher Meis | f725257 | 2025-06-11 13:22:05 +0200 | [diff] [blame] | 348 | if (!writeJsonFiles(systemConfiguration)) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 349 | { | 
| Alexander Hansen | 8feb045 | 2025-09-15 14:29:20 +0200 | [diff] [blame] | 350 | lg2::error("Error writing json files"); | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 351 | } | 
|  | 352 | std::string dbusName = *name; | 
|  | 353 |  | 
|  | 354 | std::regex_replace(dbusName.begin(), dbusName.begin(), | 
|  | 355 | dbusName.end(), illegalDbusMemberRegex, "_"); | 
|  | 356 |  | 
|  | 357 | std::shared_ptr<sdbusplus::asio::dbus_interface> interface = | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 358 | createInterface(path + "/" + dbusName, | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 359 | "xyz.openbmc_project.Configuration." + *type, | 
|  | 360 | board, true); | 
|  | 361 | // permission is read-write, as since we just created it, must be | 
|  | 362 | // runtime modifiable | 
|  | 363 | populateInterfaceFromJson( | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 364 | systemConfiguration, | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 365 | jsonPointerPath + "/Exposes/" + std::to_string(lastIndex), | 
| Alexander Hansen | 8973725 | 2025-08-04 15:15:13 +0200 | [diff] [blame] | 366 | interface, newData, | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 367 | sdbusplus::asio::PropertyPermission::readWrite); | 
|  | 368 | }); | 
|  | 369 | tryIfaceInitialize(iface); | 
|  | 370 | } | 
|  | 371 |  | 
|  | 372 | std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>& | 
| Alexander Hansen | 57604ed | 2025-06-27 13:22:28 +0200 | [diff] [blame] | 373 | EMDBusInterface::getDeviceInterfaces(const nlohmann::json& device) | 
| Christopher Meis | 12bea9b | 2025-04-03 10:14:42 +0200 | [diff] [blame] | 374 | { | 
|  | 375 | return inventory[device["Name"].get<std::string>()]; | 
|  | 376 | } | 
|  | 377 |  | 
|  | 378 | } // namespace dbus_interface |