diff --git a/include/EntityManager.hpp b/include/EntityManager.hpp
index 084174d..a79e7fe 100644
--- a/include/EntityManager.hpp
+++ b/include/EntityManager.hpp
@@ -40,6 +40,25 @@
 using FoundDeviceT = std::vector<std::tuple<
     boost::container::flat_map<std::string, BasicVariantType>, std::string>>;
 
+struct CmpStr
+{
+    bool operator()(const char* a, const char* b) const
+    {
+        return std::strcmp(a, b) < 0;
+    }
+};
+
+// underscore T for collison with dbus c api
+enum class probe_type_codes
+{
+    FALSE_T,
+    TRUE_T,
+    AND,
+    OR,
+    FOUND,
+    MATCH_ONE
+};
+
 struct PerformScan : std::enable_shared_from_this<PerformScan>
 {
 
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index 490c0f5..725f2bf 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -47,29 +47,9 @@
 constexpr const char* lastConfiguration = "/tmp/configuration/last.json";
 constexpr const char* currentConfiguration = "/var/configuration/system.json";
 constexpr const char* globalSchema = "global.json";
-constexpr const int32_t maxMapperDepth = 0;
-
 constexpr const bool debug = false;
 
-struct CmpStr
-{
-    bool operator()(const char* a, const char* b) const
-    {
-        return std::strcmp(a, b) < 0;
-    }
-};
-
-// underscore T for collison with dbus c api
-enum class probe_type_codes
-{
-    FALSE_T,
-    TRUE_T,
-    AND,
-    OR,
-    FOUND,
-    MATCH_ONE
-};
-const static boost::container::flat_map<const char*, probe_type_codes, CmpStr>
+static const boost::container::flat_map<const char*, probe_type_codes, CmpStr>
     probeTypes{{{"FALSE", probe_type_codes::FALSE_T},
                 {"TRUE", probe_type_codes::TRUE_T},
                 {"AND", probe_type_codes::AND},
@@ -83,9 +63,6 @@
     std::variant<std::vector<std::string>, std::vector<double>, std::string,
                  int64_t, uint64_t, double, int32_t, uint32_t, int16_t,
                  uint16_t, uint8_t, bool>;
-using GetSubTreeType = std::vector<
-    std::pair<std::string,
-              std::vector<std::pair<std::string, std::vector<std::string>>>>>;
 
 using ManagedObjectType = boost::container::flat_map<
     sdbusplus::message::object_path,
@@ -100,17 +77,13 @@
 
 // todo: pass this through nicer
 std::shared_ptr<sdbusplus::asio::connection> systemBus;
-static nlohmann::json lastJson;
+nlohmann::json lastJson;
 
 boost::asio::io_context io;
 
 const std::regex illegalDbusPathRegex("[^A-Za-z0-9_.]");
 const std::regex illegalDbusMemberRegex("[^A-Za-z0-9_]");
 
-void registerCallback(nlohmann::json& systemConfiguration,
-                      sdbusplus::asio::object_server& objServer,
-                      const std::string& path);
-
 static std::shared_ptr<sdbusplus::asio::dbus_interface>
     createInterface(sdbusplus::asio::object_server& objServer,
                     const std::string& path, const std::string& interface,
@@ -136,153 +109,6 @@
     return ptr;
 }
 
-void getInterfaces(
-    const std::tuple<std::string, std::string, std::string>& call,
-    const std::vector<std::shared_ptr<PerformProbe>>& probeVector,
-    const std::shared_ptr<PerformScan>& scan, size_t retries = 5)
-{
-    if (!retries)
-    {
-        std::cerr << "retries exhausted on " << std::get<0>(call) << " "
-                  << std::get<1>(call) << " " << std::get<2>(call) << "\n";
-        return;
-    }
-
-    systemBus->async_method_call(
-        [call, scan, probeVector, retries](
-            boost::system::error_code& errc,
-            const boost::container::flat_map<std::string, BasicVariantType>&
-                resp) {
-            if (errc)
-            {
-                std::cerr << "error calling getall on  " << std::get<0>(call)
-                          << " " << std::get<1>(call) << " "
-                          << std::get<2>(call) << "\n";
-
-                std::shared_ptr<boost::asio::steady_timer> timer =
-                    std::make_shared<boost::asio::steady_timer>(io);
-                timer->expires_after(std::chrono::seconds(2));
-
-                timer->async_wait([timer, call, scan, probeVector,
-                                   retries](const boost::system::error_code&) {
-                    getInterfaces(call, probeVector, scan, retries - 1);
-                });
-                return;
-            }
-
-            scan->dbusProbeObjects[std::get<1>(call)][std::get<2>(call)] = resp;
-        },
-        std::get<0>(call), std::get<1>(call), "org.freedesktop.DBus.Properties",
-        "GetAll", std::get<2>(call));
-
-    if constexpr (debug)
-    {
-        std::cerr << __func__ << " " << __LINE__ << "\n";
-    }
-}
-
-// Populates scan->dbusProbeObjects with all interfaces and properties
-// for the paths that own the interfaces passed in.
-void findDbusObjects(std::vector<std::shared_ptr<PerformProbe>>&& probeVector,
-                     boost::container::flat_set<std::string>&& interfaces,
-                     const std::shared_ptr<PerformScan>& scan,
-                     size_t retries = 5)
-{
-    // Filter out interfaces already obtained.
-    for (const auto& [path, probeInterfaces] : scan->dbusProbeObjects)
-    {
-        for (const auto& [interface, _] : probeInterfaces)
-        {
-            interfaces.erase(interface);
-        }
-    }
-    if (interfaces.empty())
-    {
-        return;
-    }
-
-    // find all connections in the mapper that expose a specific type
-    systemBus->async_method_call(
-        [interfaces, probeVector{std::move(probeVector)}, scan,
-         retries](boost::system::error_code& ec,
-                  const GetSubTreeType& interfaceSubtree) mutable {
-            boost::container::flat_set<
-                std::tuple<std::string, std::string, std::string>>
-                interfaceConnections;
-            if (ec)
-            {
-                if (ec.value() == ENOENT)
-                {
-                    return; // wasn't found by mapper
-                }
-                std::cerr << "Error communicating to mapper.\n";
-
-                if (!retries)
-                {
-                    // if we can't communicate to the mapper something is very
-                    // wrong
-                    std::exit(EXIT_FAILURE);
-                }
-                std::shared_ptr<boost::asio::steady_timer> timer =
-                    std::make_shared<boost::asio::steady_timer>(io);
-                timer->expires_after(std::chrono::seconds(10));
-
-                timer->async_wait(
-                    [timer, interfaces{std::move(interfaces)}, scan,
-                     probeVector{std::move(probeVector)},
-                     retries](const boost::system::error_code&) mutable {
-                        findDbusObjects(std::move(probeVector),
-                                        std::move(interfaces), scan,
-                                        retries - 1);
-                    });
-                return;
-            }
-
-            for (const auto& [path, object] : interfaceSubtree)
-            {
-                for (const auto& [busname, ifaces] : object)
-                {
-                    for (const std::string& iface : ifaces)
-                    {
-                        // The 3 default org.freedeskstop interfaces (Peer,
-                        // Introspectable, and Properties) are returned by
-                        // the mapper but don't have properties, so don't bother
-                        // with the GetAll call to save some cycles.
-                        if (!boost::algorithm::starts_with(iface,
-                                                           "org.freedesktop"))
-                        {
-                            interfaceConnections.emplace(busname, path, iface);
-                        }
-                    }
-                }
-
-                // Get a PropertiesChanged callback for all
-                // interfaces on this path.
-                registerCallback(scan->_systemConfiguration, scan->objServer,
-                                 path);
-            }
-
-            if (interfaceConnections.empty())
-            {
-                return;
-            }
-
-            for (const auto& call : interfaceConnections)
-            {
-                getInterfaces(call, probeVector, scan);
-            }
-        },
-        "xyz.openbmc_project.ObjectMapper",
-        "/xyz/openbmc_project/object_mapper",
-        "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", maxMapperDepth,
-        interfaces);
-
-    if constexpr (debug)
-    {
-        std::cerr << __func__ << " " << __LINE__ << "\n";
-    }
-}
-
 // probes dbus interface dictionary for a key with a value that matches a regex
 // When an interface passes a probe, also save its D-Bus path with it.
 bool probeDbus(const std::string& interface,
@@ -1213,455 +1039,6 @@
     return true;
 }
 
-std::string getRecordName(
-    const boost::container::flat_map<std::string, BasicVariantType>& probe,
-    const std::string& probeName)
-{
-    if (probe.empty())
-    {
-        return probeName;
-    }
-
-    // use an array so alphabetical order from the
-    // flat_map is maintained
-    auto device = nlohmann::json::array();
-    for (auto& devPair : probe)
-    {
-        device.push_back(devPair.first);
-        std::visit([&device](auto&& v) { device.push_back(v); },
-                   devPair.second);
-    }
-    size_t hash = std::hash<std::string>{}(probeName + device.dump());
-    // hashes are hard to distinguish, use the
-    // non-hashed version if we want debug
-    if constexpr (debug)
-    {
-        return probeName + device.dump();
-    }
-    else
-    {
-        return std::to_string(hash);
-    }
-}
-
-PerformScan::PerformScan(nlohmann::json& systemConfiguration,
-                         nlohmann::json& missingConfigurations,
-                         std::list<nlohmann::json>& configurations,
-                         sdbusplus::asio::object_server& objServerIn,
-                         std::function<void()>&& callback) :
-    _systemConfiguration(systemConfiguration),
-    _missingConfigurations(missingConfigurations),
-    _configurations(configurations), objServer(objServerIn),
-    _callback(std::move(callback))
-{}
-void PerformScan::run()
-{
-    boost::container::flat_set<std::string> dbusProbeInterfaces;
-    std::vector<std::shared_ptr<PerformProbe>> dbusProbePointers;
-
-    for (auto it = _configurations.begin(); it != _configurations.end();)
-    {
-        auto findProbe = it->find("Probe");
-        auto findName = it->find("Name");
-
-        nlohmann::json probeCommand;
-        // check for poorly formatted fields, probe must be an array
-        if (findProbe == it->end())
-        {
-            std::cerr << "configuration file missing probe:\n " << *it << "\n";
-            it = _configurations.erase(it);
-            continue;
-        }
-        if ((*findProbe).type() != nlohmann::json::value_t::array)
-        {
-            probeCommand = nlohmann::json::array();
-            probeCommand.push_back(*findProbe);
-        }
-        else
-        {
-            probeCommand = *findProbe;
-        }
-
-        if (findName == it->end())
-        {
-            std::cerr << "configuration file missing name:\n " << *it << "\n";
-            it = _configurations.erase(it);
-            continue;
-        }
-        std::string probeName = *findName;
-
-        if (std::find(passedProbes.begin(), passedProbes.end(), probeName) !=
-            passedProbes.end())
-        {
-            it = _configurations.erase(it);
-            continue;
-        }
-        nlohmann::json* recordPtr = &(*it);
-
-        // store reference to this to children to makes sure we don't get
-        // destroyed too early
-        auto thisRef = shared_from_this();
-        auto probePointer = std::make_shared<PerformProbe>(
-            probeCommand, thisRef,
-            [&, recordPtr, probeName](FoundDeviceT& foundDevices,
-                                      const DBusProbeObjectT& allInterfaces) {
-                _passed = true;
-                std::set<nlohmann::json> usedNames;
-                passedProbes.push_back(probeName);
-                std::list<size_t> indexes(foundDevices.size());
-                std::iota(indexes.begin(), indexes.end(), 1);
-
-                size_t indexIdx = probeName.find('$');
-                bool hasTemplateName = (indexIdx != std::string::npos);
-
-                // copy over persisted configurations and make sure we remove
-                // indexes that are already used
-                for (auto itr = foundDevices.begin();
-                     itr != foundDevices.end();)
-                {
-                    std::string recordName =
-                        getRecordName(std::get<0>(*itr), probeName);
-
-                    auto fromLastJson = lastJson.find(recordName);
-                    if (fromLastJson != lastJson.end())
-                    {
-                        auto findExposes = fromLastJson->find("Exposes");
-                        // delete nulls from any updates
-                        if (findExposes != fromLastJson->end())
-                        {
-                            auto copy = nlohmann::json::array();
-                            for (auto& expose : *findExposes)
-                            {
-                                if (expose.is_null())
-                                {
-                                    continue;
-                                }
-                                copy.emplace_back(expose);
-                            }
-                            *findExposes = copy;
-                        }
-
-                        // keep user changes
-                        _systemConfiguration[recordName] = *fromLastJson;
-                        _missingConfigurations.erase(recordName);
-                        itr = foundDevices.erase(itr);
-                        if (hasTemplateName)
-                        {
-                            auto nameIt = fromLastJson->find("Name");
-                            if (nameIt == fromLastJson->end())
-                            {
-                                std::cerr << "Last JSON Illegal\n";
-                                continue;
-                            }
-                            int index = 0;
-                            auto str =
-                                nameIt->get<std::string>().substr(indexIdx);
-                            auto [p, ec] = std::from_chars(
-                                str.data(), str.data() + str.size(), index);
-                            if (ec != std::errc())
-                            {
-                                continue; // non-numeric replacement
-                            }
-                            usedNames.insert(nameIt.value());
-                            auto usedIt = std::find(indexes.begin(),
-                                                    indexes.end(), index);
-
-                            if (usedIt == indexes.end())
-                            {
-                                continue; // less items now
-                            }
-                            indexes.erase(usedIt);
-                        }
-
-                        continue;
-                    }
-                    itr++;
-                }
-
-                std::optional<std::string> replaceStr;
-
-                DBusProbeObjectT::mapped_type emptyInterfaces;
-                boost::container::flat_map<std::string, BasicVariantType>
-                    emptyProps;
-                emptyInterfaces.emplace(std::string{}, emptyProps);
-
-                for (auto& foundDeviceAndPath : foundDevices)
-                {
-                    const boost::container::flat_map<
-                        std::string, BasicVariantType>& foundDevice =
-                        std::get<0>(foundDeviceAndPath);
-                    const std::string& path = std::get<1>(foundDeviceAndPath);
-
-                    // Need all interfaces on this path so that template
-                    // substitutions can be done with any of the contained
-                    // properties.  If the probe that passed didn't use an
-                    // interface, such as if it was just TRUE, then
-                    // templateCharReplace will just get passed in an empty
-                    // map.
-                    const DBusProbeObjectT::mapped_type* allInterfacesOnPath =
-                        &emptyInterfaces;
-
-                    auto ifacesIt = allInterfaces.find(path);
-                    if (ifacesIt != allInterfaces.end())
-                    {
-                        allInterfacesOnPath = &ifacesIt->second;
-                    }
-
-                    nlohmann::json record = *recordPtr;
-                    std::string recordName =
-                        getRecordName(foundDevice, probeName);
-                    size_t foundDeviceIdx = indexes.front();
-                    indexes.pop_front();
-
-                    // check name first so we have no duplicate names
-                    auto getName = record.find("Name");
-                    if (getName == record.end())
-                    {
-                        std::cerr << "Record Missing Name! " << record.dump();
-                        continue; // this should be impossible at this level
-                    }
-
-                    nlohmann::json copyForName = {{"Name", getName.value()}};
-                    nlohmann::json::iterator copyIt = copyForName.begin();
-                    std::optional<std::string> replaceVal =
-                        templateCharReplace(copyIt, *allInterfacesOnPath,
-                                            foundDeviceIdx, replaceStr);
-
-                    if (!replaceStr && replaceVal)
-                    {
-                        if (usedNames.find(copyIt.value()) != usedNames.end())
-                        {
-                            replaceStr = replaceVal;
-                            copyForName = {{"Name", getName.value()}};
-                            copyIt = copyForName.begin();
-                            templateCharReplace(copyIt, *allInterfacesOnPath,
-                                                foundDeviceIdx, replaceStr);
-                        }
-                    }
-
-                    if (replaceStr)
-                    {
-                        std::cerr << "Duplicates found, replacing "
-                                  << *replaceStr
-                                  << " with found device index.\n Consider "
-                                     "fixing template to not have duplicates\n";
-                    }
-
-                    for (auto keyPair = record.begin(); keyPair != record.end();
-                         keyPair++)
-                    {
-                        if (keyPair.key() == "Name")
-                        {
-                            keyPair.value() = copyIt.value();
-                            usedNames.insert(copyIt.value());
-
-                            continue; // already covered above
-                        }
-                        templateCharReplace(keyPair, *allInterfacesOnPath,
-                                            foundDeviceIdx, replaceStr);
-                    }
-
-                    // insert into configuration temporarily to be able to
-                    // reference ourselves
-
-                    _systemConfiguration[recordName] = record;
-
-                    auto findExpose = record.find("Exposes");
-                    if (findExpose == record.end())
-                    {
-                        _systemConfiguration[recordName] = record;
-                        continue;
-                    }
-
-                    for (auto& expose : *findExpose)
-                    {
-                        for (auto keyPair = expose.begin();
-                             keyPair != expose.end(); keyPair++)
-                        {
-
-                            templateCharReplace(keyPair, *allInterfacesOnPath,
-                                                foundDeviceIdx, replaceStr);
-
-                            bool isBind =
-                                boost::starts_with(keyPair.key(), "Bind");
-                            bool isDisable = keyPair.key() == "DisableNode";
-
-                            // special cases
-                            if (!(isBind || isDisable))
-                            {
-                                continue;
-                            }
-
-                            if (keyPair.value().type() !=
-                                    nlohmann::json::value_t::string &&
-                                keyPair.value().type() !=
-                                    nlohmann::json::value_t::array)
-                            {
-                                std::cerr << "Value is invalid type "
-                                          << keyPair.key() << "\n";
-                                continue;
-                            }
-
-                            std::vector<std::string> matches;
-                            if (keyPair.value().type() ==
-                                nlohmann::json::value_t::string)
-                            {
-                                matches.emplace_back(keyPair.value());
-                            }
-                            else
-                            {
-                                for (const auto& value : keyPair.value())
-                                {
-                                    if (value.type() !=
-                                        nlohmann::json::value_t::string)
-                                    {
-                                        std::cerr << "Value is invalid type "
-                                                  << value << "\n";
-                                        break;
-                                    }
-                                    matches.emplace_back(value);
-                                }
-                            }
-
-                            std::set<std::string> foundMatches;
-                            for (auto& configurationPair :
-                                 _systemConfiguration.items())
-                            {
-                                if (isDisable)
-                                {
-                                    // don't disable ourselves
-                                    if (configurationPair.key() == recordName)
-                                    {
-                                        continue;
-                                    }
-                                }
-                                auto configListFind =
-                                    configurationPair.value().find("Exposes");
-
-                                if (configListFind ==
-                                        configurationPair.value().end() ||
-                                    configListFind->type() !=
-                                        nlohmann::json::value_t::array)
-                                {
-                                    continue;
-                                }
-                                for (auto& exposedObject : *configListFind)
-                                {
-                                    auto matchIt = std::find_if(
-                                        matches.begin(), matches.end(),
-                                        [name = (exposedObject)["Name"]
-                                                    .get<std::string>()](
-                                            const std::string& s) {
-                                            return s == name;
-                                        });
-                                    if (matchIt == matches.end())
-                                    {
-                                        continue;
-                                    }
-                                    foundMatches.insert(*matchIt);
-
-                                    if (isBind)
-                                    {
-                                        std::string bind = keyPair.key().substr(
-                                            sizeof("Bind") - 1);
-
-                                        exposedObject["Status"] = "okay";
-                                        expose[bind] = exposedObject;
-                                    }
-                                    else if (isDisable)
-                                    {
-                                        exposedObject["Status"] = "disabled";
-                                    }
-                                }
-                            }
-                            if (foundMatches.size() != matches.size())
-                            {
-                                std::cerr << "configuration file "
-                                             "dependency error, "
-                                             "could not find "
-                                          << keyPair.key() << " "
-                                          << keyPair.value() << "\n";
-                            }
-                        }
-                    }
-                    // overwrite ourselves with cleaned up version
-                    _systemConfiguration[recordName] = record;
-                    _missingConfigurations.erase(recordName);
-                }
-            });
-
-        // parse out dbus probes by discarding other probe types, store in a
-        // map
-        for (const nlohmann::json& probeJson : probeCommand)
-        {
-            const std::string* probe = probeJson.get_ptr<const std::string*>();
-            if (probe == nullptr)
-            {
-                std::cerr << "Probe statement wasn't a string, can't parse";
-                continue;
-            }
-            bool found = false;
-            boost::container::flat_map<const char*, probe_type_codes,
-                                       CmpStr>::const_iterator probeType;
-            for (probeType = probeTypes.begin(); probeType != probeTypes.end();
-                 ++probeType)
-            {
-                if (probe->find(probeType->first) != std::string::npos)
-                {
-                    found = true;
-                    break;
-                }
-            }
-            if (found)
-            {
-                continue;
-            }
-            // syntax requires probe before first open brace
-            auto findStart = probe->find('(');
-            std::string interface = probe->substr(0, findStart);
-            dbusProbeInterfaces.emplace(interface);
-            dbusProbePointers.emplace_back(probePointer);
-        }
-        it++;
-    }
-
-    // probe vector stores a shared_ptr to each PerformProbe that cares
-    // about a dbus interface
-    findDbusObjects(std::move(dbusProbePointers),
-                    std::move(dbusProbeInterfaces), shared_from_this());
-    if constexpr (debug)
-    {
-        std::cerr << __func__ << " " << __LINE__ << "\n";
-    }
-}
-
-PerformScan::~PerformScan()
-{
-    if (_passed)
-    {
-        auto nextScan = std::make_shared<PerformScan>(
-            _systemConfiguration, _missingConfigurations, _configurations,
-            objServer, std::move(_callback));
-        nextScan->passedProbes = std::move(passedProbes);
-        nextScan->dbusProbeObjects = std::move(dbusProbeObjects);
-        nextScan->run();
-
-        if constexpr (debug)
-        {
-            std::cerr << __func__ << " " << __LINE__ << "\n";
-        }
-    }
-    else
-    {
-        _callback();
-
-        if constexpr (debug)
-        {
-            std::cerr << __func__ << " " << __LINE__ << "\n";
-        }
-    }
-}
-
 void startRemovedTimer(boost::asio::steady_timer& timer,
                        nlohmann::json& systemConfiguration)
 {
@@ -1869,31 +1246,6 @@
     });
 }
 
-void registerCallback(nlohmann::json& systemConfiguration,
-                      sdbusplus::asio::object_server& objServer,
-                      const std::string& path)
-{
-    static boost::container::flat_map<std::string, sdbusplus::bus::match::match>
-        dbusMatches;
-
-    auto find = dbusMatches.find(path);
-    if (find != dbusMatches.end())
-    {
-        return;
-    }
-    std::function<void(sdbusplus::message::message & message)> eventHandler =
-
-        [&](sdbusplus::message::message&) {
-            propertiesChangedCallback(systemConfiguration, objServer);
-        };
-
-    sdbusplus::bus::match::match match(
-        static_cast<sdbusplus::bus::bus&>(*systemBus),
-        "type='signal',member='PropertiesChanged',path='" + path + "'",
-        eventHandler);
-    dbusMatches.emplace(path, std::move(match));
-}
-
 int main()
 {
     // setup connection to dbus
diff --git a/src/PerformScan.cpp b/src/PerformScan.cpp
new file mode 100644
index 0000000..70a4e47
--- /dev/null
+++ b/src/PerformScan.cpp
@@ -0,0 +1,669 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+/// \file PerformScan.cpp
+#include "EntityManager.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/flat_set.hpp>
+
+#include <charconv>
+
+/* Hacks from splitting EntityManager.cpp */
+extern std::shared_ptr<sdbusplus::asio::connection> systemBus;
+extern nlohmann::json lastJson;
+extern void
+    propertiesChangedCallback(nlohmann::json& systemConfiguration,
+                              sdbusplus::asio::object_server& objServer);
+
+/* Keep this in sync with EntityManager.cpp */
+static const boost::container::flat_map<const char*, probe_type_codes, CmpStr>
+    probeTypes{{{"FALSE", probe_type_codes::FALSE_T},
+                {"TRUE", probe_type_codes::TRUE_T},
+                {"AND", probe_type_codes::AND},
+                {"OR", probe_type_codes::OR},
+                {"FOUND", probe_type_codes::FOUND},
+                {"MATCH_ONE", probe_type_codes::MATCH_ONE}}};
+
+using GetSubTreeType = std::vector<
+    std::pair<std::string,
+              std::vector<std::pair<std::string, std::vector<std::string>>>>>;
+
+constexpr const int32_t maxMapperDepth = 0;
+
+constexpr const bool debug = false;
+
+void getInterfaces(
+    const std::tuple<std::string, std::string, std::string>& call,
+    const std::vector<std::shared_ptr<PerformProbe>>& probeVector,
+    const std::shared_ptr<PerformScan>& scan, size_t retries = 5)
+{
+    if (!retries)
+    {
+        std::cerr << "retries exhausted on " << std::get<0>(call) << " "
+                  << std::get<1>(call) << " " << std::get<2>(call) << "\n";
+        return;
+    }
+
+    systemBus->async_method_call(
+        [call, scan, probeVector, retries](
+            boost::system::error_code& errc,
+            const boost::container::flat_map<std::string, BasicVariantType>&
+                resp) {
+            if (errc)
+            {
+                std::cerr << "error calling getall on  " << std::get<0>(call)
+                          << " " << std::get<1>(call) << " "
+                          << std::get<2>(call) << "\n";
+
+                std::shared_ptr<boost::asio::steady_timer> timer =
+                    std::make_shared<boost::asio::steady_timer>(io);
+                timer->expires_after(std::chrono::seconds(2));
+
+                timer->async_wait([timer, call, scan, probeVector,
+                                   retries](const boost::system::error_code&) {
+                    getInterfaces(call, probeVector, scan, retries - 1);
+                });
+                return;
+            }
+
+            scan->dbusProbeObjects[std::get<1>(call)][std::get<2>(call)] = resp;
+        },
+        std::get<0>(call), std::get<1>(call), "org.freedesktop.DBus.Properties",
+        "GetAll", std::get<2>(call));
+
+    if constexpr (debug)
+    {
+        std::cerr << __func__ << " " << __LINE__ << "\n";
+    }
+}
+
+void registerCallback(nlohmann::json& systemConfiguration,
+                      sdbusplus::asio::object_server& objServer,
+                      const std::string& path)
+{
+    static boost::container::flat_map<std::string, sdbusplus::bus::match::match>
+        dbusMatches;
+
+    auto find = dbusMatches.find(path);
+    if (find != dbusMatches.end())
+    {
+        return;
+    }
+    std::function<void(sdbusplus::message::message & message)> eventHandler =
+
+        [&](sdbusplus::message::message&) {
+            propertiesChangedCallback(systemConfiguration, objServer);
+        };
+
+    sdbusplus::bus::match::match match(
+        static_cast<sdbusplus::bus::bus&>(*systemBus),
+        "type='signal',member='PropertiesChanged',path='" + path + "'",
+        eventHandler);
+    dbusMatches.emplace(path, std::move(match));
+}
+
+// Populates scan->dbusProbeObjects with all interfaces and properties
+// for the paths that own the interfaces passed in.
+void findDbusObjects(std::vector<std::shared_ptr<PerformProbe>>&& probeVector,
+                     boost::container::flat_set<std::string>&& interfaces,
+                     const std::shared_ptr<PerformScan>& scan,
+                     size_t retries = 5)
+{
+    // Filter out interfaces already obtained.
+    for (const auto& [path, probeInterfaces] : scan->dbusProbeObjects)
+    {
+        for (const auto& [interface, _] : probeInterfaces)
+        {
+            interfaces.erase(interface);
+        }
+    }
+    if (interfaces.empty())
+    {
+        return;
+    }
+
+    // find all connections in the mapper that expose a specific type
+    systemBus->async_method_call(
+        [interfaces, probeVector{std::move(probeVector)}, scan,
+         retries](boost::system::error_code& ec,
+                  const GetSubTreeType& interfaceSubtree) mutable {
+            boost::container::flat_set<
+                std::tuple<std::string, std::string, std::string>>
+                interfaceConnections;
+            if (ec)
+            {
+                if (ec.value() == ENOENT)
+                {
+                    return; // wasn't found by mapper
+                }
+                std::cerr << "Error communicating to mapper.\n";
+
+                if (!retries)
+                {
+                    // if we can't communicate to the mapper something is very
+                    // wrong
+                    std::exit(EXIT_FAILURE);
+                }
+                std::shared_ptr<boost::asio::steady_timer> timer =
+                    std::make_shared<boost::asio::steady_timer>(io);
+                timer->expires_after(std::chrono::seconds(10));
+
+                timer->async_wait(
+                    [timer, interfaces{std::move(interfaces)}, scan,
+                     probeVector{std::move(probeVector)},
+                     retries](const boost::system::error_code&) mutable {
+                        findDbusObjects(std::move(probeVector),
+                                        std::move(interfaces), scan,
+                                        retries - 1);
+                    });
+                return;
+            }
+
+            for (const auto& [path, object] : interfaceSubtree)
+            {
+                for (const auto& [busname, ifaces] : object)
+                {
+                    for (const std::string& iface : ifaces)
+                    {
+                        // The 3 default org.freedeskstop interfaces (Peer,
+                        // Introspectable, and Properties) are returned by
+                        // the mapper but don't have properties, so don't bother
+                        // with the GetAll call to save some cycles.
+                        if (!boost::algorithm::starts_with(iface,
+                                                           "org.freedesktop"))
+                        {
+                            interfaceConnections.emplace(busname, path, iface);
+                        }
+                    }
+                }
+
+                // Get a PropertiesChanged callback for all
+                // interfaces on this path.
+                registerCallback(scan->_systemConfiguration, scan->objServer,
+                                 path);
+            }
+
+            if (interfaceConnections.empty())
+            {
+                return;
+            }
+
+            for (const auto& call : interfaceConnections)
+            {
+                getInterfaces(call, probeVector, scan);
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", maxMapperDepth,
+        interfaces);
+
+    if constexpr (debug)
+    {
+        std::cerr << __func__ << " " << __LINE__ << "\n";
+    }
+}
+
+std::string getRecordName(
+    const boost::container::flat_map<std::string, BasicVariantType>& probe,
+    const std::string& probeName)
+{
+    if (probe.empty())
+    {
+        return probeName;
+    }
+
+    // use an array so alphabetical order from the
+    // flat_map is maintained
+    auto device = nlohmann::json::array();
+    for (auto& devPair : probe)
+    {
+        device.push_back(devPair.first);
+        std::visit([&device](auto&& v) { device.push_back(v); },
+                   devPair.second);
+    }
+    size_t hash = std::hash<std::string>{}(probeName + device.dump());
+    // hashes are hard to distinguish, use the
+    // non-hashed version if we want debug
+    if constexpr (debug)
+    {
+        return probeName + device.dump();
+    }
+    else
+    {
+        return std::to_string(hash);
+    }
+}
+
+PerformScan::PerformScan(nlohmann::json& systemConfiguration,
+                         nlohmann::json& missingConfigurations,
+                         std::list<nlohmann::json>& configurations,
+                         sdbusplus::asio::object_server& objServerIn,
+                         std::function<void()>&& callback) :
+    _systemConfiguration(systemConfiguration),
+    _missingConfigurations(missingConfigurations),
+    _configurations(configurations), objServer(objServerIn),
+    _callback(std::move(callback))
+{}
+void PerformScan::run()
+{
+    boost::container::flat_set<std::string> dbusProbeInterfaces;
+    std::vector<std::shared_ptr<PerformProbe>> dbusProbePointers;
+
+    for (auto it = _configurations.begin(); it != _configurations.end();)
+    {
+        auto findProbe = it->find("Probe");
+        auto findName = it->find("Name");
+
+        nlohmann::json probeCommand;
+        // check for poorly formatted fields, probe must be an array
+        if (findProbe == it->end())
+        {
+            std::cerr << "configuration file missing probe:\n " << *it << "\n";
+            it = _configurations.erase(it);
+            continue;
+        }
+        if ((*findProbe).type() != nlohmann::json::value_t::array)
+        {
+            probeCommand = nlohmann::json::array();
+            probeCommand.push_back(*findProbe);
+        }
+        else
+        {
+            probeCommand = *findProbe;
+        }
+
+        if (findName == it->end())
+        {
+            std::cerr << "configuration file missing name:\n " << *it << "\n";
+            it = _configurations.erase(it);
+            continue;
+        }
+        std::string probeName = *findName;
+
+        if (std::find(passedProbes.begin(), passedProbes.end(), probeName) !=
+            passedProbes.end())
+        {
+            it = _configurations.erase(it);
+            continue;
+        }
+        nlohmann::json* recordPtr = &(*it);
+
+        // store reference to this to children to makes sure we don't get
+        // destroyed too early
+        auto thisRef = shared_from_this();
+        auto probePointer = std::make_shared<PerformProbe>(
+            probeCommand, thisRef,
+            [&, recordPtr, probeName](FoundDeviceT& foundDevices,
+                                      const DBusProbeObjectT& allInterfaces) {
+                _passed = true;
+                std::set<nlohmann::json> usedNames;
+                passedProbes.push_back(probeName);
+                std::list<size_t> indexes(foundDevices.size());
+                std::iota(indexes.begin(), indexes.end(), 1);
+
+                size_t indexIdx = probeName.find('$');
+                bool hasTemplateName = (indexIdx != std::string::npos);
+
+                // copy over persisted configurations and make sure we remove
+                // indexes that are already used
+                for (auto itr = foundDevices.begin();
+                     itr != foundDevices.end();)
+                {
+                    std::string recordName =
+                        getRecordName(std::get<0>(*itr), probeName);
+
+                    auto fromLastJson = lastJson.find(recordName);
+                    if (fromLastJson != lastJson.end())
+                    {
+                        auto findExposes = fromLastJson->find("Exposes");
+                        // delete nulls from any updates
+                        if (findExposes != fromLastJson->end())
+                        {
+                            auto copy = nlohmann::json::array();
+                            for (auto& expose : *findExposes)
+                            {
+                                if (expose.is_null())
+                                {
+                                    continue;
+                                }
+                                copy.emplace_back(expose);
+                            }
+                            *findExposes = copy;
+                        }
+
+                        // keep user changes
+                        _systemConfiguration[recordName] = *fromLastJson;
+                        _missingConfigurations.erase(recordName);
+                        itr = foundDevices.erase(itr);
+                        if (hasTemplateName)
+                        {
+                            auto nameIt = fromLastJson->find("Name");
+                            if (nameIt == fromLastJson->end())
+                            {
+                                std::cerr << "Last JSON Illegal\n";
+                                continue;
+                            }
+                            int index = 0;
+                            auto str =
+                                nameIt->get<std::string>().substr(indexIdx);
+                            auto [p, ec] = std::from_chars(
+                                str.data(), str.data() + str.size(), index);
+                            if (ec != std::errc())
+                            {
+                                continue; // non-numeric replacement
+                            }
+                            usedNames.insert(nameIt.value());
+                            auto usedIt = std::find(indexes.begin(),
+                                                    indexes.end(), index);
+
+                            if (usedIt == indexes.end())
+                            {
+                                continue; // less items now
+                            }
+                            indexes.erase(usedIt);
+                        }
+
+                        continue;
+                    }
+                    itr++;
+                }
+
+                std::optional<std::string> replaceStr;
+
+                DBusProbeObjectT::mapped_type emptyInterfaces;
+                boost::container::flat_map<std::string, BasicVariantType>
+                    emptyProps;
+                emptyInterfaces.emplace(std::string{}, emptyProps);
+
+                for (auto& foundDeviceAndPath : foundDevices)
+                {
+                    const boost::container::flat_map<
+                        std::string, BasicVariantType>& foundDevice =
+                        std::get<0>(foundDeviceAndPath);
+                    const std::string& path = std::get<1>(foundDeviceAndPath);
+
+                    // Need all interfaces on this path so that template
+                    // substitutions can be done with any of the contained
+                    // properties.  If the probe that passed didn't use an
+                    // interface, such as if it was just TRUE, then
+                    // templateCharReplace will just get passed in an empty
+                    // map.
+                    const DBusProbeObjectT::mapped_type* allInterfacesOnPath =
+                        &emptyInterfaces;
+
+                    auto ifacesIt = allInterfaces.find(path);
+                    if (ifacesIt != allInterfaces.end())
+                    {
+                        allInterfacesOnPath = &ifacesIt->second;
+                    }
+
+                    nlohmann::json record = *recordPtr;
+                    std::string recordName =
+                        getRecordName(foundDevice, probeName);
+                    size_t foundDeviceIdx = indexes.front();
+                    indexes.pop_front();
+
+                    // check name first so we have no duplicate names
+                    auto getName = record.find("Name");
+                    if (getName == record.end())
+                    {
+                        std::cerr << "Record Missing Name! " << record.dump();
+                        continue; // this should be impossible at this level
+                    }
+
+                    nlohmann::json copyForName = {{"Name", getName.value()}};
+                    nlohmann::json::iterator copyIt = copyForName.begin();
+                    std::optional<std::string> replaceVal =
+                        templateCharReplace(copyIt, *allInterfacesOnPath,
+                                            foundDeviceIdx, replaceStr);
+
+                    if (!replaceStr && replaceVal)
+                    {
+                        if (usedNames.find(copyIt.value()) != usedNames.end())
+                        {
+                            replaceStr = replaceVal;
+                            copyForName = {{"Name", getName.value()}};
+                            copyIt = copyForName.begin();
+                            templateCharReplace(copyIt, *allInterfacesOnPath,
+                                                foundDeviceIdx, replaceStr);
+                        }
+                    }
+
+                    if (replaceStr)
+                    {
+                        std::cerr << "Duplicates found, replacing "
+                                  << *replaceStr
+                                  << " with found device index.\n Consider "
+                                     "fixing template to not have duplicates\n";
+                    }
+
+                    for (auto keyPair = record.begin(); keyPair != record.end();
+                         keyPair++)
+                    {
+                        if (keyPair.key() == "Name")
+                        {
+                            keyPair.value() = copyIt.value();
+                            usedNames.insert(copyIt.value());
+
+                            continue; // already covered above
+                        }
+                        templateCharReplace(keyPair, *allInterfacesOnPath,
+                                            foundDeviceIdx, replaceStr);
+                    }
+
+                    // insert into configuration temporarily to be able to
+                    // reference ourselves
+
+                    _systemConfiguration[recordName] = record;
+
+                    auto findExpose = record.find("Exposes");
+                    if (findExpose == record.end())
+                    {
+                        _systemConfiguration[recordName] = record;
+                        continue;
+                    }
+
+                    for (auto& expose : *findExpose)
+                    {
+                        for (auto keyPair = expose.begin();
+                             keyPair != expose.end(); keyPair++)
+                        {
+
+                            templateCharReplace(keyPair, *allInterfacesOnPath,
+                                                foundDeviceIdx, replaceStr);
+
+                            bool isBind =
+                                boost::starts_with(keyPair.key(), "Bind");
+                            bool isDisable = keyPair.key() == "DisableNode";
+
+                            // special cases
+                            if (!(isBind || isDisable))
+                            {
+                                continue;
+                            }
+
+                            if (keyPair.value().type() !=
+                                    nlohmann::json::value_t::string &&
+                                keyPair.value().type() !=
+                                    nlohmann::json::value_t::array)
+                            {
+                                std::cerr << "Value is invalid type "
+                                          << keyPair.key() << "\n";
+                                continue;
+                            }
+
+                            std::vector<std::string> matches;
+                            if (keyPair.value().type() ==
+                                nlohmann::json::value_t::string)
+                            {
+                                matches.emplace_back(keyPair.value());
+                            }
+                            else
+                            {
+                                for (const auto& value : keyPair.value())
+                                {
+                                    if (value.type() !=
+                                        nlohmann::json::value_t::string)
+                                    {
+                                        std::cerr << "Value is invalid type "
+                                                  << value << "\n";
+                                        break;
+                                    }
+                                    matches.emplace_back(value);
+                                }
+                            }
+
+                            std::set<std::string> foundMatches;
+                            for (auto& configurationPair :
+                                 _systemConfiguration.items())
+                            {
+                                if (isDisable)
+                                {
+                                    // don't disable ourselves
+                                    if (configurationPair.key() == recordName)
+                                    {
+                                        continue;
+                                    }
+                                }
+                                auto configListFind =
+                                    configurationPair.value().find("Exposes");
+
+                                if (configListFind ==
+                                        configurationPair.value().end() ||
+                                    configListFind->type() !=
+                                        nlohmann::json::value_t::array)
+                                {
+                                    continue;
+                                }
+                                for (auto& exposedObject : *configListFind)
+                                {
+                                    auto matchIt = std::find_if(
+                                        matches.begin(), matches.end(),
+                                        [name = (exposedObject)["Name"]
+                                                    .get<std::string>()](
+                                            const std::string& s) {
+                                            return s == name;
+                                        });
+                                    if (matchIt == matches.end())
+                                    {
+                                        continue;
+                                    }
+                                    foundMatches.insert(*matchIt);
+
+                                    if (isBind)
+                                    {
+                                        std::string bind = keyPair.key().substr(
+                                            sizeof("Bind") - 1);
+
+                                        exposedObject["Status"] = "okay";
+                                        expose[bind] = exposedObject;
+                                    }
+                                    else if (isDisable)
+                                    {
+                                        exposedObject["Status"] = "disabled";
+                                    }
+                                }
+                            }
+                            if (foundMatches.size() != matches.size())
+                            {
+                                std::cerr << "configuration file "
+                                             "dependency error, "
+                                             "could not find "
+                                          << keyPair.key() << " "
+                                          << keyPair.value() << "\n";
+                            }
+                        }
+                    }
+                    // overwrite ourselves with cleaned up version
+                    _systemConfiguration[recordName] = record;
+                    _missingConfigurations.erase(recordName);
+                }
+            });
+
+        // parse out dbus probes by discarding other probe types, store in a
+        // map
+        for (const nlohmann::json& probeJson : probeCommand)
+        {
+            const std::string* probe = probeJson.get_ptr<const std::string*>();
+            if (probe == nullptr)
+            {
+                std::cerr << "Probe statement wasn't a string, can't parse";
+                continue;
+            }
+            bool found = false;
+            boost::container::flat_map<const char*, probe_type_codes,
+                                       CmpStr>::const_iterator probeType;
+            for (probeType = probeTypes.begin(); probeType != probeTypes.end();
+                 ++probeType)
+            {
+                if (probe->find(probeType->first) != std::string::npos)
+                {
+                    found = true;
+                    break;
+                }
+            }
+            if (found)
+            {
+                continue;
+            }
+            // syntax requires probe before first open brace
+            auto findStart = probe->find('(');
+            std::string interface = probe->substr(0, findStart);
+            dbusProbeInterfaces.emplace(interface);
+            dbusProbePointers.emplace_back(probePointer);
+        }
+        it++;
+    }
+
+    // probe vector stores a shared_ptr to each PerformProbe that cares
+    // about a dbus interface
+    findDbusObjects(std::move(dbusProbePointers),
+                    std::move(dbusProbeInterfaces), shared_from_this());
+    if constexpr (debug)
+    {
+        std::cerr << __func__ << " " << __LINE__ << "\n";
+    }
+}
+
+PerformScan::~PerformScan()
+{
+    if (_passed)
+    {
+        auto nextScan = std::make_shared<PerformScan>(
+            _systemConfiguration, _missingConfigurations, _configurations,
+            objServer, std::move(_callback));
+        nextScan->passedProbes = std::move(passedProbes);
+        nextScan->dbusProbeObjects = std::move(dbusProbeObjects);
+        nextScan->run();
+
+        if constexpr (debug)
+        {
+            std::cerr << __func__ << " " << __LINE__ << "\n";
+        }
+    }
+    else
+    {
+        _callback();
+
+        if constexpr (debug)
+        {
+            std::cerr << __func__ << " " << __LINE__ << "\n";
+        }
+    }
+}
diff --git a/src/meson.build b/src/meson.build
index 8a9811b..bab416c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -3,6 +3,7 @@
 executable(
     'entity-manager',
     'EntityManager.cpp',
+    'PerformScan.cpp',
     'Overlay.cpp',
     'Utils.cpp',
     cpp_args: cpp_args + ['-DBOOST_ASIO_DISABLE_THREADS'],
