diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
new file mode 100644
index 0000000..950644f
--- /dev/null
+++ b/src/EntityManager.cpp
@@ -0,0 +1,634 @@
+/*
+// 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.
+*/
+
+#include <Utils.hpp>
+#include <dbus/properties.hpp>
+#include <nlohmann/json.hpp>
+#include <fstream>
+#include <regex>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/flat_set.hpp>
+#include <VariantVisitors.hpp>
+
+constexpr const char *OUTPUT_DIR = "/var/configuration/";
+constexpr const char *CONFIGURATION_DIR = "/usr/share/configurations";
+constexpr const char *TEMPLATE_CHAR = "$";
+constexpr const size_t MAX_MAPPER_DEPTH = 99;
+
+namespace fs = std::experimental::filesystem;
+struct cmp_str
+{
+    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
+};
+const static boost::container::flat_map<const char *, probe_type_codes, cmp_str>
+    PROBE_TYPES{{{"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}}};
+
+using GetSubTreeType = std::vector<
+    std::pair<std::string,
+              std::vector<std::pair<std::string, std::vector<std::string>>>>>;
+
+using ManagedObjectType = boost::container::flat_map<
+    dbus::object_path,
+    boost::container::flat_map<
+        std::string,
+        boost::container::flat_map<std::string, dbus::dbus_variant>>>;
+
+boost::container::flat_map<
+    std::string,
+    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>>
+    DBUS_PROBE_OBJECTS;
+std::vector<std::string> PASSED_PROBES;
+
+// todo: pass this through nicer
+std::shared_ptr<dbus::connection> SYSTEM_BUS;
+
+// calls the mapper to find all exposed objects of an interface type
+// and creates a vector<flat_map> that contains all the key value pairs
+// getManagedObjects
+bool findDbusObjects(
+    std::shared_ptr<dbus::connection> connection,
+    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>
+        &interfaceDevices,
+    std::string interface)
+{
+    // find all connections in the mapper that expose a specific type
+    static const dbus::endpoint mapper("xyz.openbmc_project.ObjectMapper",
+                                       "/xyz/openbmc_project/object_mapper",
+                                       "xyz.openbmc_project.ObjectMapper",
+                                       "GetSubTree");
+    dbus::message getMap = dbus::message::new_call(mapper);
+    std::vector<std::string> objects = {interface};
+    if (!getMap.pack("", MAX_MAPPER_DEPTH, objects))
+    {
+        std::cerr << "Pack Failed GetSensorSubtree\n";
+        return false;
+    }
+    dbus::message getMapResp = connection->send(getMap);
+    GetSubTreeType interfaceSubtree;
+    if (!getMapResp.unpack(interfaceSubtree))
+    {
+        std::cerr << "Error communicating to mapper\n";
+        return false;
+    }
+    boost::container::flat_set<std::string> connections;
+    for (auto &object : interfaceSubtree)
+    {
+        for (auto &connPair : object.second)
+        {
+            connections.insert(connPair.first);
+        }
+    }
+    // iterate through the connections, adding creating individual device
+    // dictionaries
+    for (auto &conn : connections)
+    {
+        auto managedObj =
+            dbus::endpoint(conn, "/", "org.freedesktop.DBus.ObjectManager",
+                           "GetManagedObjects");
+        dbus::message getManagedObj = dbus::message::new_call(managedObj);
+        dbus::message getManagedObjResp = connection->send(getManagedObj);
+        ManagedObjectType managedInterface;
+        if (!getManagedObjResp.unpack(managedInterface))
+        {
+            std::cerr << "error getting managed object for device " << conn
+                      << "\n";
+            continue;
+        }
+        for (auto &interfaceManagedObj : managedInterface)
+        {
+            auto ifaceObjFind = interfaceManagedObj.second.find(interface);
+            if (ifaceObjFind != interfaceManagedObj.second.end())
+            {
+                interfaceDevices.emplace_back(ifaceObjFind->second);
+            }
+        }
+    }
+    return true;
+}
+
+// probes interface dictionary for a key with a value that matches a regex
+bool probeDbus(
+    const std::string &interface,
+    const std::map<std::string, nlohmann::json> &matches,
+    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>
+        &devices,
+    bool &foundProbe)
+{
+    auto &dbusObject = DBUS_PROBE_OBJECTS[interface];
+    if (dbusObject.empty())
+    {
+        if (!findDbusObjects(SYSTEM_BUS, dbusObject, interface))
+        {
+            std::cerr << "Found no dbus objects with interface "
+                      << interface << "\n";
+            foundProbe = false;
+            return false;
+        }
+    }
+    foundProbe = true;
+
+    bool foundMatch = false;
+    for (auto &device : dbusObject)
+    {
+        bool deviceMatches = true;
+        for (auto &match : matches)
+        {
+            auto deviceValue = device.find(match.first);
+            if (deviceValue != device.end())
+            {
+                switch (match.second.type())
+                {
+                case nlohmann::json::value_t::string:
+                {
+                    std::regex search(match.second.get<std::string>());
+                    std::smatch match;
+
+                    // convert value to string respresentation
+                    std::string probeValue = boost::apply_visitor(
+                        [](const auto &x) {
+                            return boost::lexical_cast<std::string>(x);
+                        },
+                        deviceValue->second);
+                    if (!std::regex_search(probeValue, match, search))
+                    {
+                        deviceMatches = false;
+                        break;
+                    }
+                    break;
+                }
+                case nlohmann::json::value_t::boolean:
+                case nlohmann::json::value_t::number_unsigned:
+                {
+                    unsigned int probeValue = boost::apply_visitor(
+                        VariantToUnsignedIntVisitor(), deviceValue->second);
+
+                    if (probeValue != match.second.get<unsigned int>())
+                    {
+                        deviceMatches = false;
+                    }
+                    break;
+                }
+                case nlohmann::json::value_t::number_integer:
+                {
+                    int probeValue = boost::apply_visitor(VariantToIntVisitor(),
+                                                          deviceValue->second);
+
+                    if (probeValue != match.second.get<int>())
+                    {
+                        deviceMatches = false;
+                    }
+                    break;
+                }
+                case nlohmann::json::value_t::number_float:
+                {
+                    float probeValue = boost::apply_visitor(
+                        VariantToFloatVisitor(), deviceValue->second);
+
+                    if (probeValue != match.second.get<float>())
+                    {
+                        deviceMatches = false;
+                    }
+                    break;
+                }
+                }
+            }
+            else
+            {
+                deviceMatches = false;
+                break;
+            }
+        }
+        if (deviceMatches)
+        {
+            devices.emplace_back(
+                boost::container::flat_map<std::string, dbus::dbus_variant>(
+                    device));
+            foundMatch = true;
+            deviceMatches = false; // for next iteration
+        }
+    }
+    return foundMatch;
+}
+
+// default probe entry point, iterates a list looking for specific types to
+// call specific probe functions
+bool probe(
+    const std::vector<std::string> probeCommand,
+    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>
+        &foundDevs)
+{
+    const static std::regex command(R"(\((.*)\))");
+    std::smatch match;
+    bool ret = false;
+    bool cur = true;
+    probe_type_codes lastCommand = probe_type_codes::FALSE_T;
+
+    for (auto &probe : probeCommand)
+    {
+        bool foundProbe = false;
+        boost::container::flat_map<const char *, probe_type_codes,
+                                   cmp_str>::const_iterator probeType;
+
+        for (probeType = PROBE_TYPES.begin(); probeType != PROBE_TYPES.end();
+             probeType++)
+        {
+            if (probe.find(probeType->first) != std::string::npos)
+            {
+                foundProbe = true;
+                break;
+            }
+        }
+        if (foundProbe)
+        {
+            switch (probeType->second)
+            {
+            case probe_type_codes::FALSE_T:
+            {
+                return false; // todo, actually evaluate?
+                break;
+            }
+            case probe_type_codes::TRUE_T:
+            {
+                return true; // todo, actually evaluate?
+                break;
+            }
+            /*case probe_type_codes::AND:
+              break;
+            case probe_type_codes::OR:
+              break;
+              // these are no-ops until the last command switch
+              */
+            case probe_type_codes::FOUND:
+            {
+                if (!std::regex_search(probe, match, command))
+                {
+                    std::cerr << "found probe sytax error " << probe << "\n";
+                    return false;
+                }
+                std::string commandStr = *(match.begin() + 1);
+                commandStr = boost::replace_all_copy(commandStr, "'", "");
+                cur = (std::find(PASSED_PROBES.begin(), PASSED_PROBES.end(),
+                                 commandStr) != PASSED_PROBES.end());
+                break;
+            }
+            }
+        }
+        // look on dbus for object
+        else
+        {
+            if (!std::regex_search(probe, match, command))
+            {
+                std::cerr << "dbus probe sytax error " << probe << "\n";
+                return false;
+            }
+            std::string commandStr = *(match.begin() + 1);
+            // convert single ticks and single slashes into legal json
+            commandStr = boost::replace_all_copy(commandStr, "'", R"(")");
+            commandStr = boost::replace_all_copy(commandStr, R"(\)", R"(\\)");
+            auto json = nlohmann::json::parse(commandStr, nullptr, false);
+            if (json.is_discarded())
+            {
+                std::cerr << "dbus command sytax error " << commandStr << "\n";
+                return false;
+            }
+            // we can match any (string, variant) property. (string, string)
+            // does a regex
+            std::map<std::string, nlohmann::json> dbusProbeMap =
+                json.get<std::map<std::string, nlohmann::json>>();
+            auto findStart = probe.find("(");
+            if (findStart == std::string::npos)
+            {
+                return false;
+            }
+            std::string probeInterface = probe.substr(0, findStart);
+            cur =
+                probeDbus(probeInterface, dbusProbeMap, foundDevs, foundProbe);
+        }
+
+        // some functions like AND and OR only take affect after the
+        // fact
+        switch (lastCommand)
+        {
+        case probe_type_codes::AND:
+            ret = cur && ret;
+            break;
+        case probe_type_codes::OR:
+            ret = cur || ret;
+            break;
+        default:
+            ret = cur;
+            break;
+        }
+        lastCommand = probeType != PROBE_TYPES.end()
+                          ? probeType->second
+                          : probe_type_codes::FALSE_T;
+
+        if (!foundProbe)
+        {
+            std::cerr << "Illegal probe type " << probe << "\n";
+            return false;
+        }
+    }
+
+    // probe passed, but empty device
+    // todo: should this be done in main?
+    if (ret && foundDevs.size() == 0)
+    {
+        foundDevs.emplace_back(
+            boost::container::flat_map<std::string, dbus::dbus_variant>());
+    }
+    return ret;
+}
+
+int main(int argc, char **argv)
+{
+    // find configuration files
+    std::vector<fs::path> jsonPaths;
+    if (!find_files(fs::path(CONFIGURATION_DIR), R"(.*\.json)", jsonPaths, 0))
+    {
+        std::cerr << "Unable to find any configuration files in "
+                  << CONFIGURATION_DIR << "\n";
+        return 1;
+    }
+    // setup connection to dbus
+    boost::asio::io_service io;
+    SYSTEM_BUS = std::make_shared<dbus::connection>(io, dbus::bus::system);
+    dbus::DbusObjectServer objServer(SYSTEM_BUS);
+    SYSTEM_BUS->request_name("xyz.openbmc_project.EntityManager");
+
+    std::vector<nlohmann::json> configurations;
+    for (auto &jsonPath : jsonPaths)
+    {
+        std::ifstream jsonStream(jsonPath.c_str());
+        if (!jsonStream.good())
+        {
+            std::cerr << "unable to open " << jsonPath.string() << "\n";
+            continue;
+        }
+        auto data = nlohmann::json::parse(jsonStream, nullptr, false);
+        if (data.is_discarded())
+        {
+            std::cerr << "syntax error in " << jsonPath.string() << "\n";
+            continue;
+        }
+        if (data.type() == nlohmann::json::value_t::array)
+        {
+            for (auto &d : data)
+            {
+                configurations.emplace_back(d);
+            }
+        }
+        else
+        {
+            configurations.emplace_back(data);
+        }
+    }
+
+    // keep looping as long as at least 1 new probe passed, removing
+    // configurations from the memory store once the probe passes
+    bool probePassed = true;
+    nlohmann::json systemConfiguration;
+    while (probePassed)
+    {
+        probePassed = false;
+        for (auto it = configurations.begin(); it != configurations.end();)
+        {
+            bool eraseConfig = false;
+            auto findProbe = (*it).find("probe");
+            auto findName = (*it).find("name");
+
+            // check for poorly formatted fields
+            if (findProbe == (*it).end())
+            {
+                std::cerr << "configuration file missing probe:\n " << *it
+                          << "\n";
+                eraseConfig = true;
+            }
+            if (findName == (*it).end())
+            {
+                std::cerr << "configuration file missing name:\n " << *it
+                          << "\n";
+                eraseConfig = true;
+            }
+
+            nlohmann::json probeCommand;
+            if ((*findProbe).type() != nlohmann::json::value_t::array)
+            {
+                probeCommand = nlohmann::json::array();
+                probeCommand.push_back(*findProbe);
+            }
+            else
+            {
+                probeCommand = *findProbe;
+            }
+            std::vector<
+                boost::container::flat_map<std::string, dbus::dbus_variant>>
+                foundDevices;
+            if (probe(probeCommand, foundDevices))
+            {
+                eraseConfig = true;
+                probePassed = true;
+                PASSED_PROBES.push_back(*findName);
+
+                size_t foundDeviceIdx = 0;
+
+                for (auto &foundDevice : foundDevices)
+                {
+                    auto findExpose = (*it).find("exposes");
+                    if (findExpose == (*it).end())
+                    {
+                        std::cerr
+                            << "Warning, configuration file missing exposes"
+                            << *it << "\n";
+                        continue;
+                    }
+                    for (auto &expose : *findExpose)
+                    {
+                        for (auto keyPair = expose.begin();
+                             keyPair != expose.end(); keyPair++)
+                        {
+                            // fill in template characters with devices
+                            // found
+                            if (keyPair.value().type() ==
+                                nlohmann::json::value_t::string)
+                            {
+                                std::string value = keyPair.value();
+                                if (value.find(TEMPLATE_CHAR) !=
+                                    std::string::npos)
+                                {
+                                    std::string templateValue = value;
+
+                                    templateValue.erase(
+                                        0, 1); // remove template character
+
+                                    // special case index
+                                    if ("index" == templateValue)
+                                    {
+                                        keyPair.value() = foundDeviceIdx;
+                                    }
+                                    else
+                                    {
+                                        std::string subsitute;
+                                        for (auto &foundDevicePair :
+                                             foundDevice)
+                                        {
+                                            if (boost::iequals(
+                                                    foundDevicePair.first,
+                                                    templateValue))
+                                            {
+                                                // convert value to string
+                                                // respresentation
+                                                subsitute =
+                                                    boost::apply_visitor(
+                                                        [](const auto &x) {
+                                                            return boost::
+                                                                lexical_cast<
+                                                                    std::
+                                                                        string>(
+                                                                    x);
+                                                        },
+                                                        foundDevicePair.second);
+                                                break;
+                                            }
+                                        }
+                                        if (!subsitute.size())
+                                        {
+                                            std::cerr << "could not find "
+                                                      << templateValue
+                                                      << " in device "
+                                                      << expose["name"] << "\n";
+                                        }
+                                        else
+                                        {
+                                            keyPair.value() = subsitute;
+                                        }
+                                    }
+                                }
+
+                                // special case bind
+                                if (boost::starts_with(keyPair.key(), "bind_"))
+                                {
+                                    bool foundBind = false;
+                                    std::string bind = keyPair.key().substr(
+                                        sizeof("bind_") - 1);
+                                    for (auto &configuration :
+                                         systemConfiguration)
+                                    {
+                                        auto &configList =
+                                            configuration["exposes"];
+                                        for (auto exposedObjectIt =
+                                                 configList.begin();
+                                             exposedObjectIt !=
+                                             configList.end();)
+                                        {
+                                            std::string foundObjectName =
+                                                (*exposedObjectIt)["name"];
+                                            if (boost::iequals(foundObjectName,
+                                                               value))
+                                            {
+                                                (*exposedObjectIt)["status"] =
+                                                    "okay"; // todo: is this the
+                                                            // right spot?
+                                                expose[bind] =
+                                                    (*exposedObjectIt);
+                                                foundBind = true;
+                                                exposedObjectIt =
+                                                    configList.erase(
+                                                        exposedObjectIt);
+                                                break;
+                                            }
+                                            else
+                                            {
+                                                exposedObjectIt++;
+                                            }
+                                        }
+                                        if (foundBind)
+                                        {
+                                            break;
+                                        }
+                                    }
+                                    if (!foundBind)
+                                    {
+                                        std::cerr << "configuration file "
+                                                     "dependency error, "
+                                                     "could not find bind "
+                                                  << value << "\n";
+                                        return 1;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    systemConfiguration.push_back(*it);
+                    foundDeviceIdx++;
+                }
+            }
+
+            if (eraseConfig)
+            {
+                it = configurations.erase(it);
+            }
+            else
+            {
+                it++;
+            }
+        }
+    }
+    // below here is temporary, to be added to dbus
+    std::ofstream output(std::string(OUTPUT_DIR) + "system.json");
+    output << systemConfiguration.dump(4);
+    output.close();
+
+    auto flat = nlohmann::json::array();
+    for (auto &pair : nlohmann::json::iterator_wrapper(systemConfiguration))
+    {
+        auto value = pair.value();
+        auto exposes = value.find("exposes");
+        if (exposes != value.end())
+        {
+            for (auto &item : *exposes)
+            {
+                flat.push_back(item);
+            }
+        }
+    }
+    output = std::ofstream(std::string(OUTPUT_DIR) + "flattened.json");
+    output << flat.dump(4);
+    output.close();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
new file mode 100644
index 0000000..b431f81
--- /dev/null
+++ b/src/FruDevice.cpp
@@ -0,0 +1,476 @@
+/*
+// 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.
+*/
+
+#include <Utils.hpp>
+#include <boost/container/flat_map.hpp>
+#include <ctime>
+#include <dbus/connection.hpp>
+#include <dbus/endpoint.hpp>
+#include <dbus/message.hpp>
+#include <dbus/properties.hpp>
+#include <fcntl.h>
+#include <fstream>
+#include <future>
+#include <i2c-dev-user.h>
+#include <iostream>
+#include <sys/ioctl.h>
+
+namespace fs = std::experimental::filesystem;
+static constexpr bool DEBUG = false;
+static size_t UNKNOWN_BUS_OBJECT_COUNT = 0;
+
+const static constexpr char *BASEBOARD_FRU_LOCATION =
+    "/etc/fru/baseboard.fru.bin";
+
+static constexpr std::array<const char *, 5> FRU_AREAS = {
+    "INTERNAL", "CHASSIS", "BOARD", "PRODUCT", "MULTIRECORD"};
+
+using DeviceMap = boost::container::flat_map<int, std::vector<char>>;
+using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
+
+int get_bus_frus(int file, int first, int last, int bus,
+                 std::shared_ptr<DeviceMap> devices)
+{
+    std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> block_data;
+
+    for (int ii = first; ii <= last; ii++)
+    {
+        // Set slave address
+        if (ioctl(file, I2C_SLAVE_FORCE, ii) < 0)
+        {
+            std::cerr << "device at bus " << bus << "register " << ii
+                      << "busy\n";
+            continue;
+        }
+        // probe
+        else if (i2c_smbus_read_byte(file) < 0)
+        {
+            continue;
+        }
+
+        if (DEBUG)
+        {
+            std::cout << "something at bus " << bus << "addr " << ii << "\n";
+        }
+        if (i2c_smbus_read_i2c_block_data(file, 0x0, 0x8, block_data.data()) <
+            0)
+        {
+            std::cerr << "failed to read bus " << bus << " address " << ii
+                      << "\n";
+            continue;
+        }
+        size_t sum = 0;
+        for (int jj = 0; jj < 7; jj++)
+        {
+            sum += block_data[jj];
+        }
+        sum = (256 - sum) & 0xFF;
+
+        // check the header checksum
+        if (sum == block_data[7])
+        {
+            std::vector<char> device;
+            device.insert(device.end(), block_data.begin(),
+                          block_data.begin() + 8);
+
+            for (int jj = 1; jj <= FRU_AREAS.size(); jj++)
+            {
+                auto area_offset = device[jj];
+                if (area_offset != 0)
+                {
+                    area_offset *= 8;
+                    if (i2c_smbus_read_i2c_block_data(file, area_offset, 0x8,
+                                                      block_data.data()) < 0)
+                    {
+                        std::cerr << "failed to read bus " << bus << " address "
+                                  << ii << "\n";
+                        return -1;
+                    }
+                    int length = block_data[1] * 8;
+                    device.insert(device.end(), block_data.begin(),
+                                  block_data.begin() + 8);
+                    length -= 8;
+                    area_offset += 8;
+
+                    while (length > 0)
+                    {
+                        auto to_get = std::min(0x20, length);
+                        if (i2c_smbus_read_i2c_block_data(
+                                file, area_offset, to_get, block_data.data()) <
+                            0)
+                        {
+                            std::cerr << "failed to read bus " << bus
+                                      << " address " << ii << "\n";
+                            return -1;
+                        }
+                        device.insert(device.end(), block_data.begin(),
+                                      block_data.begin() + to_get);
+                        area_offset += to_get;
+                        length -= to_get;
+                    }
+                }
+            }
+            (*devices).emplace(ii, device);
+        }
+    }
+
+    return 0;
+}
+
+static BusMap FindI2CDevices(const std::vector<fs::path> &i2cBuses)
+{
+    static std::vector<std::future<void>> futures;
+    BusMap busMap;
+    for (auto &i2cBus : i2cBuses)
+    {
+        auto busnum = i2cBus.string();
+        auto lastDash = busnum.rfind(std::string("-"));
+        // delete everything before dash inclusive
+        if (lastDash != std::string::npos)
+        {
+            busnum.erase(0, lastDash + 1);
+        }
+        auto bus = std::stoi(busnum);
+
+        auto file = open(i2cBus.c_str(), O_RDWR);
+        if (file < 0)
+        {
+            std::cerr << "unable to open i2c device " << i2cBus.string()
+                      << "\n";
+            continue;
+        }
+        unsigned long funcs = 0;
+
+        if (ioctl(file, I2C_FUNCS, &funcs) < 0)
+        {
+            std::cerr
+                << "Error: Could not get the adapter functionality matrix bus"
+                << bus << "\n";
+            continue;
+        }
+        if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE) ||
+            !(I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+        {
+            std::cerr << "Error: Can't use SMBus Receive Byte command bus "
+                      << bus << "\n";
+            continue;
+        }
+        auto &device = busMap[bus];
+        device = std::make_shared<DeviceMap>();
+
+        // todo: call with boost asio?
+        futures.emplace_back(
+            std::async(std::launch::async, [file, device, bus] {
+                //  i2cdetect by default uses the range 0x03 to 0x77, as this is
+                //  what we
+                //  have tested with, use this range. Could be changed in
+                //  future.
+                get_bus_frus(file, 0x03, 0x77, bus, device);
+                close(file);
+            }));
+    }
+    for (auto &fut : futures)
+    {
+        fut.get(); // wait for all scans
+    }
+    return busMap;
+}
+
+static const std::tm intelEpoch(void)
+{
+    std::tm val = {0};
+    val.tm_year = 1996 - 1900;
+    return val;
+}
+
+bool formatFru(const std::vector<char> &fruBytes,
+               boost::container::flat_map<std::string, std::string> &result)
+{
+    static const std::vector<const char *> CHASSIS_FRU_AREAS = {
+        "PART_NUMBER", "SERIAL_NUMBER", "CHASSIS_INFO_AM1", "CHASSIS_INFO_AM2"};
+
+    static const std::vector<const char *> BOARD_FRU_AREAS = {
+        "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
+        "VERSION_ID"};
+
+    static const std::vector<const char *> PRODUCT_FRU_AREAS = {
+        "MANUFACTURER",    "PRODUCT_NAME",          "PART_NUMBER",
+        "PRODUCT_VERSION", "PRODUCT_SERIAL_NUMBER", "ASSET_TAG"};
+
+    size_t sum = 0;
+
+    if (fruBytes.size() < 8)
+    {
+        return false;
+    }
+    std::vector<char>::const_iterator fruAreaOffsetField = fruBytes.begin();
+    result["Common Format Version"] =
+        std::to_string(static_cast<int>(*fruAreaOffsetField));
+
+    const std::vector<const char *> *fieldData;
+
+    for (auto &area : FRU_AREAS)
+    {
+        fruAreaOffsetField++;
+        if (fruAreaOffsetField >= fruBytes.end())
+        {
+            return false;
+        }
+        size_t offset = (*fruAreaOffsetField) * 8;
+
+        if (offset > 1)
+        {
+            // +2 to skip format and length
+            std::vector<char>::const_iterator fruBytesIter =
+                fruBytes.begin() + offset + 2;
+
+            if (fruBytesIter >= fruBytes.end())
+            {
+                return false;
+            }
+
+            if (area == "CHASSIS")
+            {
+                result["CHASSIS_TYPE"] =
+                    std::to_string(static_cast<int>(*fruBytesIter));
+                fruBytesIter += 1;
+                fieldData = &CHASSIS_FRU_AREAS;
+            }
+            else if (area == "BOARD")
+            {
+                result["BOARD_LANGUAGE_CODE"] =
+                    std::to_string(static_cast<int>(*fruBytesIter));
+                fruBytesIter += 1;
+                if (fruBytesIter >= fruBytes.end())
+                {
+                    return false;
+                }
+
+                unsigned int minutes = *fruBytesIter |
+                                       *(fruBytesIter + 1) << 8 |
+                                       *(fruBytesIter + 2) << 16;
+                std::tm fruTime = intelEpoch();
+                time_t timeValue = mktime(&fruTime);
+                timeValue += minutes * 60;
+                fruTime = *gmtime(&timeValue);
+
+                result["BOARD_MANUFACTURE_DATE"] = asctime(&fruTime);
+                result["BOARD_MANUFACTURE_DATE"]
+                    .pop_back(); // remove trailing null
+                fruBytesIter += 3;
+                fieldData = &BOARD_FRU_AREAS;
+            }
+            else if (area == "PRODUCT")
+            {
+                result["PRODUCT_LANGUAGE_CODE"] =
+                    std::to_string(static_cast<int>(*fruBytesIter));
+                fruBytesIter += 1;
+                fieldData = &PRODUCT_FRU_AREAS;
+            }
+            else
+            {
+                continue;
+            }
+            for (auto &field : *fieldData)
+            {
+                if (fruBytesIter >= fruBytes.end())
+                {
+                    return false;
+                }
+
+                size_t length = *fruBytesIter & 0x3f;
+                fruBytesIter += 1;
+
+                if (fruBytesIter >= fruBytes.end())
+                {
+                    return false;
+                }
+
+                result[std::string(area) + "_" + field] =
+                    std::string(fruBytesIter, fruBytesIter + length);
+                fruBytesIter += length;
+                if (fruBytesIter >= fruBytes.end())
+                {
+                    std::cerr << "Warning Fru Length Mismatch:\n    ";
+                    for (auto &c : fruBytes)
+                    {
+                        std::cerr << c;
+                    }
+                    std::cerr << "\n";
+                    if (DEBUG)
+                    {
+                        for (auto &keyPair : result)
+                        {
+                            std::cerr << keyPair.first << " : "
+                                      << keyPair.second << "\n";
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+void AddFruObjectToDbus(
+    std::shared_ptr<dbus::connection> dbusConn, std::vector<char> &device,
+    dbus::DbusObjectServer &objServer,
+    boost::container::flat_map<std::pair<size_t, size_t>,
+                               std::shared_ptr<dbus::DbusObject>>
+        &dbusObjectMap,
+    int bus, size_t address)
+{
+    boost::container::flat_map<std::string, std::string> formattedFru;
+    if (!formatFru(device, formattedFru))
+    {
+        std::cerr << "failed to format fru for device at bus " << std::hex
+                  << bus << "address " << address << "\n";
+        return;
+    }
+    auto productNameFind = formattedFru.find("BOARD_PRODUCT_NAME");
+    std::string productName;
+    if (productNameFind == formattedFru.end())
+    {
+        productNameFind = formattedFru.find("PRODUCT_PRODUCT_NAME");
+    }
+    if (productNameFind != formattedFru.end())
+    {
+        productName = productNameFind->second;
+    }
+    else
+    {
+        productName = "UNKNOWN" + std::to_string(UNKNOWN_BUS_OBJECT_COUNT);
+        UNKNOWN_BUS_OBJECT_COUNT++;
+    }
+
+    auto object =
+        objServer.add_object("/xyz/openbmc_project/FruDevice/" + productName);
+    dbusObjectMap[std::pair<size_t, size_t>(bus, address)] = object;
+
+    auto iface = std::make_shared<dbus::DbusInterface>(
+        "xyz.openbmc_project.FruDevice", dbusConn);
+    object->register_interface(iface);
+    for (auto &property : formattedFru)
+    {
+        iface->set_property(property.first, property.second);
+    }
+    // baseboard can set this to -1 to not set a bus / address
+    if (bus > 0)
+    {
+        std::stringstream data;
+        data << "0x" << std::hex << bus;
+        iface->set_property("BUS", data.str());
+        data.str("");
+        data << "0x" << std::hex << address;
+        iface->set_property("ADDRESS", data.str());
+    }
+}
+
+static bool readBaseboardFru(std::vector<char> &baseboardFru)
+{
+    // try to read baseboard fru from file
+    std::ifstream baseboardFruFile(BASEBOARD_FRU_LOCATION, std::ios::binary);
+    if (baseboardFruFile.good())
+    {
+        baseboardFruFile.seekg(0, std::ios_base::end);
+        std::streampos fileSize = baseboardFruFile.tellg();
+        baseboardFru.resize(fileSize);
+        baseboardFruFile.seekg(0, std::ios_base::beg);
+        baseboardFruFile.read(baseboardFru.data(), fileSize);
+    }
+    else
+    {
+        return false;
+    }
+    return true;
+}
+
+int main(int argc, char **argv)
+{
+    auto devDir = fs::path("/dev/");
+    auto matchString = std::string("i2c*");
+    std::vector<fs::path> i2cBuses;
+
+    if (!find_files(devDir, matchString, i2cBuses, 0))
+    {
+        std::cerr << "unable to find i2c devices\n";
+        return 1;
+    }
+    BusMap busMap = FindI2CDevices(i2cBuses);
+
+    boost::asio::io_service io;
+    auto systemBus = std::make_shared<dbus::connection>(io, dbus::bus::system);
+    dbus::DbusObjectServer objServer(systemBus);
+    systemBus->request_name("com.intel.FruDevice");
+
+    // this is a map with keys of pair(bus number, adddress) and values of the
+    // object on dbus
+    boost::container::flat_map<std::pair<size_t, size_t>,
+                               std::shared_ptr<dbus::DbusObject>>
+        dbusObjectMap;
+
+    for (auto &devicemap : busMap)
+    {
+        for (auto &device : *devicemap.second)
+        {
+            AddFruObjectToDbus(systemBus, device.second, objServer,
+                               dbusObjectMap, devicemap.first, device.first);
+        }
+    }
+
+    std::vector<char> baseboardFru;
+    if (readBaseboardFru(baseboardFru))
+    {
+        AddFruObjectToDbus(systemBus, baseboardFru, objServer, dbusObjectMap,
+                           -1, -1);
+    }
+
+    auto object = std::make_shared<dbus::DbusObject>(
+        systemBus, "/xyz/openbmc_project/FruDevice");
+    objServer.register_object(object);
+    auto iface = std::make_shared<dbus::DbusInterface>(
+        "xyz.openbmc_project.FruDeviceManager", systemBus);
+    object->register_interface(iface);
+
+    iface->register_method("ReScan", [&]() {
+        busMap = FindI2CDevices(i2cBuses);
+
+        for (auto &busObj : dbusObjectMap)
+        {
+            objServer.remove_object(busObj.second);
+        }
+        dbusObjectMap.clear();
+        UNKNOWN_BUS_OBJECT_COUNT = 0;
+
+        for (auto &devicemap : busMap)
+        {
+            for (auto &device : *devicemap.second)
+            {
+                AddFruObjectToDbus(systemBus, device.second, objServer,
+                                   dbusObjectMap, devicemap.first,
+                                   device.first);
+            }
+        }
+
+        return std::tuple<>(); // this is a bug in boost-dbus, needs some sort
+                               // of return
+    });
+
+    io.run();
+    return 0;
+}
diff --git a/src/Utils.cpp b/src/Utils.cpp
new file mode 100644
index 0000000..e63861e
--- /dev/null
+++ b/src/Utils.cpp
@@ -0,0 +1,49 @@
+/*
+// Copyright (c) 2017 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.
+*/
+
+#include <Utils.hpp>
+#include <experimental/filesystem>
+#include <fstream>
+#include <regex>
+
+namespace fs = std::experimental::filesystem;
+
+bool find_files(const fs::path &dir_path, const std::string &match_string,
+                std::vector<fs::path> &found_paths, unsigned int symlink_depth)
+{
+    if (!fs::exists(dir_path))
+        return false;
+
+    fs::directory_iterator end_itr;
+    std::regex search(match_string);
+    std::smatch match;
+    for (auto &p : fs::recursive_directory_iterator(dir_path))
+    {
+        std::string path = p.path().string();
+        if (!is_directory(p))
+        {
+            if (std::regex_search(path, match, search))
+                found_paths.emplace_back(p.path());
+        }
+        // since we're using a recursve iterator, these should only be symlink
+        // dirs
+        else if (symlink_depth)
+        {
+            find_files(p.path(), match_string, found_paths, symlink_depth - 1);
+        }
+    }
+    return true;
+}
\ No newline at end of file
