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'],
