diff --git a/src/overlay.cpp b/src/overlay.cpp
new file mode 100644
index 0000000..1d99a79
--- /dev/null
+++ b/src/overlay.cpp
@@ -0,0 +1,385 @@
+/*
+// 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 overlay.cpp
+
+#include "overlay.hpp"
+
+#include "utils.hpp"
+#include "devices.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/process/child.hpp>
+#include <nlohmann/json.hpp>
+
+#include <filesystem>
+#include <iomanip>
+#include <iostream>
+#include <regex>
+#include <string>
+
+constexpr const char* outputDir = "/tmp/overlays";
+constexpr const char* templateChar = "$";
+constexpr const char* i2CDevsDir = "/sys/bus/i2c/devices";
+constexpr const char* muxSymlinkDir = "/dev/i2c-mux";
+
+constexpr const bool debug = false;
+
+std::regex illegalNameRegex("[^A-Za-z0-9_]");
+
+// helper function to make json types into string
+std::string jsonToString(const nlohmann::json& in)
+{
+    if (in.type() == nlohmann::json::value_t::string)
+    {
+        return in.get<std::string>();
+    }
+    if (in.type() == nlohmann::json::value_t::array)
+    {
+        // remove brackets and comma from array
+        std::string array = in.dump();
+        array = array.substr(1, array.size() - 2);
+        boost::replace_all(array, ",", " ");
+        return array;
+    }
+    return in.dump();
+}
+
+void linkMux(const std::string& muxName, size_t busIndex, size_t address,
+             const nlohmann::json::array_t& channelNames)
+{
+    std::error_code ec;
+    std::filesystem::path muxSymlinkDirPath(muxSymlinkDir);
+    std::filesystem::create_directory(muxSymlinkDirPath, ec);
+    // ignore error codes here if the directory already exists
+    ec.clear();
+    std::filesystem::path linkDir = muxSymlinkDirPath / muxName;
+    std::filesystem::create_directory(linkDir, ec);
+
+    std::ostringstream hexAddress;
+    hexAddress << std::hex << std::setfill('0') << std::setw(4) << address;
+
+    std::filesystem::path devDir(i2CDevsDir);
+    devDir /= std::to_string(busIndex) + "-" + hexAddress.str();
+
+    for (std::size_t channelIndex = 0; channelIndex < channelNames.size();
+         channelIndex++)
+    {
+        const std::string* channelName =
+            channelNames[channelIndex].get_ptr<const std::string*>();
+        if (channelName == nullptr)
+        {
+            continue;
+        }
+        if (channelName->empty())
+        {
+            continue;
+        }
+
+        std::filesystem::path channelPath =
+            devDir / ("channel-" + std::to_string(channelIndex));
+        if (!is_symlink(channelPath))
+        {
+            std::cerr << channelPath << "for mux channel " << *channelName
+                      << " doesn't exist!\n";
+            continue;
+        }
+        std::filesystem::path bus = std::filesystem::read_symlink(channelPath);
+
+        std::filesystem::path fp("/dev" / bus.filename());
+        std::filesystem::path link(linkDir / *channelName);
+
+        std::filesystem::create_symlink(fp, link, ec);
+        if (ec)
+        {
+            std::cerr << "Failure creating symlink for " << fp << " to " << link
+                      << "\n";
+        }
+    }
+}
+
+static int deleteDevice(const std::string& devicePath,
+                        const std::shared_ptr<uint64_t>& address,
+                        const std::string& destructor)
+{
+    if (!address)
+    {
+        return -1;
+    }
+    std::filesystem::path deviceDestructor(devicePath);
+    deviceDestructor /= destructor;
+    std::ofstream deviceFile(deviceDestructor);
+    if (!deviceFile.good())
+    {
+        std::cerr << "Error writing " << deviceDestructor << "\n";
+        return -1;
+    }
+    deviceFile << std::to_string(*address);
+    deviceFile.close();
+    return 0;
+}
+
+static int createDevice(const std::string& devicePath,
+                        const std::string& parameters,
+                        const std::string& constructor)
+{
+    std::filesystem::path deviceConstructor(devicePath);
+    deviceConstructor /= constructor;
+    std::ofstream deviceFile(deviceConstructor);
+    if (!deviceFile.good())
+    {
+        std::cerr << "Error writing " << deviceConstructor << "\n";
+        return -1;
+    }
+    deviceFile << parameters;
+    deviceFile.close();
+
+    return 0;
+}
+
+static bool deviceIsCreated(const std::string& devicePath,
+                            const std::shared_ptr<uint64_t>& bus,
+                            const std::shared_ptr<uint64_t>& address,
+                            const bool retrying)
+{
+    if (!bus || !address)
+    {
+        return false;
+    }
+
+    std::ostringstream hex;
+    hex << std::hex << std::setw(4) << std::setfill('0') << *address;
+    std::string addressHex = hex.str();
+    std::string busStr = std::to_string(*bus);
+
+    std::error_code ec;
+    auto path = std::filesystem::recursive_directory_iterator(devicePath, ec);
+    if (ec)
+    {
+        std::cerr << "Unable to open path " << devicePath << "\n";
+        return false;
+    }
+    for (; path != std::filesystem::recursive_directory_iterator(); path++)
+    {
+        if (!std::filesystem::is_directory(*path))
+        {
+            continue;
+        }
+
+        const std::string directoryName = path->path().filename();
+        std::string name = busStr;
+        name += "-";
+        name += addressHex;
+        if (directoryName == name)
+        {
+            // The first time the BMC boots the kernel has creates a
+            // filesystem enumerating the I2C devices. The I2C device has not
+            // been initialized for use. This requires a call to a device
+            // node, such as "new_device". The first pass through this
+            // function is only confirming the filesystem contains the device
+            // entry of interest (i.e. i2c4-0050).
+            //
+            // An upper level function performs the device creation
+            // action. This action may fail. The device driver (dd) used to
+            // create the I2C filesystem substructure eats any error codes,
+            // and always returns 0. This is by design. It is also possible
+            // for the new_device action to fail because the device is not
+            // actually in the system, i.e. optional equipment.
+            //
+            // The 'retrying' pass of this function is used to confirm the
+            // 'dd' device driver succeeded. Success is measured by finding
+            // the 'hwmon' subdirectory in the filesystem. The first attempt
+            // is delayed by an arbitrary amount, in order to permit the
+            // kernel time to create the filesystem entries. The upper level
+            // function determines the number of times to retry calling this
+            // function.
+            if (retrying)
+            {
+                std::error_code ec;
+                std::filesystem::path hwmonDir(devicePath);
+                hwmonDir /= directoryName;
+                hwmonDir /= "hwmon";
+                return std::filesystem::is_directory(hwmonDir, ec);
+            }
+            return true;
+        }
+        path.disable_recursion_pending();
+    }
+    return false;
+}
+
+static int buildDevice(const std::string& devicePath,
+                       const std::string& parameters,
+                       const std::shared_ptr<uint64_t>& bus,
+                       const std::shared_ptr<uint64_t>& address,
+                       const std::string& constructor,
+                       const std::string& destructor, const bool createsHWMon,
+                       const size_t retries = 5)
+{
+    bool tryAgain = false;
+    if (!retries)
+    {
+        return -1;
+    }
+
+    if (!deviceIsCreated(devicePath, bus, address, false))
+    {
+        createDevice(devicePath, parameters, constructor);
+        tryAgain = true;
+    }
+    else if (createsHWMon && !deviceIsCreated(devicePath, bus, address, true))
+    {
+        // device is present, hwmon subdir missing
+        deleteDevice(devicePath, address, destructor);
+        tryAgain = true;
+    }
+
+    if (tryAgain)
+    {
+        std::shared_ptr<boost::asio::steady_timer> createTimer =
+            std::make_shared<boost::asio::steady_timer>(io);
+        createTimer->expires_after(std::chrono::milliseconds(500));
+        createTimer->async_wait([createTimer, devicePath, parameters, bus,
+                                 address, constructor, destructor, createsHWMon,
+                                 retries](const boost::system::error_code& ec) {
+            if (ec)
+            {
+                std::cerr << "Timer error: " << ec << "\n";
+                return -2;
+            }
+            return buildDevice(devicePath, parameters, bus, address,
+                               constructor, destructor, createsHWMon,
+                               retries - 1);
+        });
+    }
+    return 0;
+}
+
+void exportDevice(const std::string& type,
+                  const devices::ExportTemplate& exportTemplate,
+                  const nlohmann::json& configuration)
+{
+
+    std::string parameters = exportTemplate.parameters;
+    std::string devicePath = exportTemplate.devicePath;
+    std::string constructor = exportTemplate.add;
+    std::string destructor = exportTemplate.remove;
+    bool createsHWMon = exportTemplate.createsHWMon;
+    std::string name = "unknown";
+    std::shared_ptr<uint64_t> bus = nullptr;
+    std::shared_ptr<uint64_t> address = nullptr;
+    const nlohmann::json::array_t* channels = nullptr;
+
+    for (auto keyPair = configuration.begin(); keyPair != configuration.end();
+         keyPair++)
+    {
+        std::string subsituteString;
+
+        if (keyPair.key() == "Name" &&
+            keyPair.value().type() == nlohmann::json::value_t::string)
+        {
+            subsituteString = std::regex_replace(
+                keyPair.value().get<std::string>(), illegalNameRegex, "_");
+            name = subsituteString;
+        }
+        else
+        {
+            subsituteString = jsonToString(keyPair.value());
+        }
+
+        if (keyPair.key() == "Bus")
+        {
+            bus = std::make_shared<uint64_t>(
+                *keyPair.value().get_ptr<const uint64_t*>());
+        }
+        else if (keyPair.key() == "Address")
+        {
+            address = std::make_shared<uint64_t>(
+                *keyPair.value().get_ptr<const uint64_t*>());
+        }
+        else if (keyPair.key() == "ChannelNames")
+        {
+            channels =
+                keyPair.value().get_ptr<const nlohmann::json::array_t*>();
+        }
+        boost::replace_all(parameters, templateChar + keyPair.key(),
+                           subsituteString);
+        boost::replace_all(devicePath, templateChar + keyPair.key(),
+                           subsituteString);
+    }
+
+    int err = buildDevice(devicePath, parameters, bus, address, constructor,
+                          destructor, createsHWMon);
+
+    if (!err && boost::ends_with(type, "Mux") && bus && address && channels)
+    {
+        linkMux(name, static_cast<size_t>(*bus), static_cast<size_t>(*address),
+                *channels);
+    }
+}
+
+bool loadOverlays(const nlohmann::json& systemConfiguration)
+{
+    std::filesystem::create_directory(outputDir);
+    for (auto entity = systemConfiguration.begin();
+         entity != systemConfiguration.end(); entity++)
+    {
+        auto findExposes = entity.value().find("Exposes");
+        if (findExposes == entity.value().end() ||
+            findExposes->type() != nlohmann::json::value_t::array)
+        {
+            continue;
+        }
+
+        for (auto& configuration : *findExposes)
+        {
+            auto findStatus = configuration.find("Status");
+            // status missing is assumed to be 'okay'
+            if (findStatus != configuration.end() && *findStatus == "disabled")
+            {
+                continue;
+            }
+            auto findType = configuration.find("Type");
+            if (findType == configuration.end() ||
+                findType->type() != nlohmann::json::value_t::string)
+            {
+                continue;
+            }
+            std::string type = findType.value().get<std::string>();
+            auto device = devices::exportTemplates.find(type.c_str());
+            if (device != devices::exportTemplates.end())
+            {
+                exportDevice(type, device->second, configuration);
+                continue;
+            }
+
+            // Because many devices are intentionally not exportable,
+            // this error message is not printed in all situations.
+            // If wondering why your device not appearing, add your type to
+            // the exportTemplates array in the devices.hpp file.
+            if constexpr (debug)
+            {
+                std::cerr << "Device type " << type
+                          << " not found in export map whitelist\n";
+            }
+        }
+    }
+
+    return true;
+}
