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";
+        }
+    }
+}
