diff --git a/src/fru_device/fru_device.cpp b/src/fru_device/fru_device.cpp
new file mode 100644
index 0000000..89b9d5a
--- /dev/null
+++ b/src/fru_device/fru_device.cpp
@@ -0,0 +1,1534 @@
+/*
+// 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 fru_device.cpp
+
+#include "../utils.hpp"
+#include "fru_utils.hpp"
+
+#include <fcntl.h>
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+
+#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 <nlohmann/json.hpp>
+#include <phosphor-logging/lg2.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <array>
+#include <cerrno>
+#include <charconv>
+#include <chrono>
+#include <ctime>
+#include <filesystem>
+#include <fstream>
+#include <functional>
+#include <future>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <map>
+#include <optional>
+#include <regex>
+#include <set>
+#include <sstream>
+#include <string>
+#include <thread>
+#include <utility>
+#include <variant>
+#include <vector>
+
+extern "C"
+{
+#include <i2c/smbus.h>
+#include <linux/i2c-dev.h>
+}
+
+namespace fs = std::filesystem;
+constexpr size_t maxFruSize = 512;
+constexpr size_t maxEepromPageIndex = 255;
+constexpr size_t busTimeoutSeconds = 10;
+
+constexpr const char* blocklistPath = PACKAGE_DIR "blacklist.json";
+
+const static constexpr char* baseboardFruLocation =
+    "/etc/fru/baseboard.fru.bin";
+
+const static constexpr char* i2CDevLocation = "/dev";
+
+constexpr const char* fruDevice16BitDetectMode = FRU_DEVICE_16BITDETECTMODE;
+
+// TODO Refactor these to not be globals
+// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
+static boost::container::flat_map<size_t, std::optional<std::set<size_t>>>
+    busBlocklist;
+struct FindDevicesWithCallback;
+
+static boost::container::flat_map<
+    std::pair<size_t, size_t>, std::shared_ptr<sdbusplus::asio::dbus_interface>>
+    foundDevices;
+
+static boost::container::flat_map<size_t, std::set<size_t>> failedAddresses;
+static boost::container::flat_map<size_t, std::set<size_t>> fruAddresses;
+
+boost::asio::io_context io;
+// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
+
+bool updateFRUProperty(
+    const std::string& updatePropertyReq, uint32_t bus, uint32_t address,
+    const std::string& propertyName,
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    size_t& unknownBusObjectCount, const bool& powerIsOn,
+    sdbusplus::asio::object_server& objServer,
+    std::shared_ptr<sdbusplus::asio::connection>& systemBus);
+
+// Given a bus/address, produce the path in sysfs for an eeprom.
+static std::string getEepromPath(size_t bus, size_t address)
+{
+    std::stringstream output;
+    output << "/sys/bus/i2c/devices/" << bus << "-" << std::right
+           << std::setfill('0') << std::setw(4) << std::hex << address
+           << "/eeprom";
+    return output.str();
+}
+
+static bool hasEepromFile(size_t bus, size_t address)
+{
+    auto path = getEepromPath(bus, address);
+    try
+    {
+        return fs::exists(path);
+    }
+    catch (...)
+    {
+        return false;
+    }
+}
+
+static int64_t readFromEeprom(int fd, off_t offset, size_t len, uint8_t* buf)
+{
+    auto result = lseek(fd, offset, SEEK_SET);
+    if (result < 0)
+    {
+        std::cerr << "failed to seek\n";
+        return -1;
+    }
+
+    return read(fd, buf, len);
+}
+
+static int busStrToInt(const std::string_view busName)
+{
+    auto findBus = busName.rfind('-');
+    if (findBus == std::string::npos)
+    {
+        return -1;
+    }
+    std::string_view num = busName.substr(findBus + 1);
+    int val = 0;
+    std::from_chars(num.data(), num.data() + num.size(), val);
+    return val;
+}
+
+static int getRootBus(size_t bus)
+{
+    auto ec = std::error_code();
+    auto path = std::filesystem::read_symlink(
+        std::filesystem::path(
+            "/sys/bus/i2c/devices/i2c-" + std::to_string(bus) + "/mux_device"),
+        ec);
+    if (ec)
+    {
+        return -1;
+    }
+
+    std::string filename = path.filename();
+    auto findBus = filename.find('-');
+    if (findBus == std::string::npos)
+    {
+        return -1;
+    }
+    return std::stoi(filename.substr(0, findBus));
+}
+
+static bool isMuxBus(size_t bus)
+{
+    auto ec = std::error_code();
+    auto isSymlink =
+        is_symlink(std::filesystem::path("/sys/bus/i2c/devices/i2c-" +
+                                         std::to_string(bus) + "/mux_device"),
+                   ec);
+    return (!ec && isSymlink);
+}
+
+static void makeProbeInterface(size_t bus, size_t address,
+                               sdbusplus::asio::object_server& objServer)
+{
+    if (isMuxBus(bus))
+    {
+        return; // the mux buses are random, no need to publish
+    }
+    auto [it, success] = foundDevices.emplace(
+        std::make_pair(bus, address),
+        objServer.add_interface(
+            "/xyz/openbmc_project/FruDevice/" + std::to_string(bus) + "_" +
+                std::to_string(address),
+            "xyz.openbmc_project.Inventory.Item.I2CDevice"));
+    if (!success)
+    {
+        return; // already added
+    }
+    it->second->register_property("Bus", bus);
+    it->second->register_property("Address", address);
+    it->second->initialize();
+}
+
+// Issue an I2C transaction to first write to_target_buf_len bytes,then read
+// from_target_buf_len bytes.
+static int i2cSmbusWriteThenRead(
+    int file, uint16_t address, uint8_t* toTargetBuf, uint8_t toTargetBufLen,
+    uint8_t* fromTargetBuf, uint8_t fromTargetBufLen)
+{
+    if (toTargetBuf == nullptr || toTargetBufLen == 0 ||
+        fromTargetBuf == nullptr || fromTargetBufLen == 0)
+    {
+        return -1;
+    }
+
+    constexpr size_t smbusWriteThenReadMsgCount = 2;
+    std::array<struct i2c_msg, smbusWriteThenReadMsgCount> msgs{};
+    struct i2c_rdwr_ioctl_data rdwr{};
+
+    msgs[0].addr = address;
+    msgs[0].flags = 0;
+    msgs[0].len = toTargetBufLen;
+    msgs[0].buf = toTargetBuf;
+    msgs[1].addr = address;
+    msgs[1].flags = I2C_M_RD;
+    msgs[1].len = fromTargetBufLen;
+    msgs[1].buf = fromTargetBuf;
+
+    rdwr.msgs = msgs.data();
+    rdwr.nmsgs = msgs.size();
+
+    int ret = ioctl(file, I2C_RDWR, &rdwr);
+
+    return (ret == static_cast<int>(msgs.size())) ? msgs[1].len : -1;
+}
+
+static int64_t readData(bool is16bit, bool isBytewise, int file,
+                        uint16_t address, off_t offset, size_t len,
+                        uint8_t* buf)
+{
+    if (!is16bit)
+    {
+        if (!isBytewise)
+        {
+            return i2c_smbus_read_i2c_block_data(
+                file, static_cast<uint8_t>(offset), len, buf);
+        }
+
+        std::span<uint8_t> bufspan{buf, len};
+        for (size_t i = 0; i < len; i++)
+        {
+            int byte = i2c_smbus_read_byte_data(
+                file, static_cast<uint8_t>(offset + i));
+            if (byte < 0)
+            {
+                return static_cast<int64_t>(byte);
+            }
+            bufspan[i] = static_cast<uint8_t>(byte);
+        }
+        return static_cast<int64_t>(len);
+    }
+
+    offset = htobe16(offset);
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+    uint8_t* u8Offset = reinterpret_cast<uint8_t*>(&offset);
+    return i2cSmbusWriteThenRead(file, address, u8Offset, 2, buf, len);
+}
+
+// Mode_1:
+// --------
+// Please refer to document docs/address_size_detection_modes.md for
+// more details and explanations.
+static std::optional<bool> isDevice16BitMode1(int file)
+{
+    // Set the higher data word address bits to 0. It's safe on 8-bit
+    // addressing EEPROMs because it doesn't write any actual data.
+    int ret = i2c_smbus_write_byte(file, 0);
+    if (ret < 0)
+    {
+        return std::nullopt;
+    }
+
+    /* Get first byte */
+    int byte1 = i2c_smbus_read_byte_data(file, 0);
+    if (byte1 < 0)
+    {
+        return std::nullopt;
+    }
+    /* Read 7 more bytes, it will read same first byte in case of
+     * 8 bit but it will read next byte in case of 16 bit
+     */
+    for (int i = 0; i < 7; i++)
+    {
+        int byte2 = i2c_smbus_read_byte_data(file, 0);
+        if (byte2 < 0)
+        {
+            return std::nullopt;
+        }
+        if (byte2 != byte1)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+// Mode_2:
+// --------
+// Please refer to document docs/address_size_detection_modes.md for
+// more details and explanations.
+static std::optional<bool> isDevice16BitMode2(int file, uint16_t address)
+{
+    uint8_t first = 0;
+    uint8_t cur = 0;
+    uint16_t v = 0;
+    int ret = 0;
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+    uint8_t* p = reinterpret_cast<uint8_t*>(&v);
+
+    /*
+     * Write 2 bytes byte0 = 0, byte1 = {0..7} and then subsequent read byte
+     * It will read same first byte in case of 8 bit but
+     * it will read next byte in case of 16 bit
+     */
+    for (int i = 0; i < 8; i++)
+    {
+        v = htobe16(i);
+
+        ret = i2cSmbusWriteThenRead(file, address, p, 2, &cur, 1);
+        if (ret < 0)
+        {
+            return std::nullopt;
+        }
+
+        if (i == 0)
+        {
+            first = cur;
+        }
+
+        if (first != cur)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+static std::optional<bool> isDevice16Bit(int file, uint16_t address)
+{
+    std::string mode(fruDevice16BitDetectMode);
+
+    if (mode == "MODE_2")
+    {
+        return isDevice16BitMode2(file, address);
+    }
+
+    return isDevice16BitMode1(file);
+}
+
+// TODO: This code is very similar to the non-eeprom version and can be merged
+// with some tweaks.
+static std::vector<uint8_t> processEeprom(int bus, int address)
+{
+    auto path = getEepromPath(bus, address);
+
+    int file = open(path.c_str(), O_RDONLY);
+    if (file < 0)
+    {
+        std::cerr << "Unable to open eeprom file: " << path << "\n";
+        return {};
+    }
+
+    std::string errorMessage = "eeprom at " + std::to_string(bus) +
+                               " address " + std::to_string(address);
+    auto readFunc = [file](off_t offset, size_t length, uint8_t* outbuf) {
+        return readFromEeprom(file, offset, length, outbuf);
+    };
+    FRUReader reader(std::move(readFunc));
+    std::pair<std::vector<uint8_t>, bool> pair =
+        readFRUContents(reader, errorMessage);
+
+    close(file);
+    return pair.first;
+}
+
+std::set<size_t> findI2CEeproms(int i2cBus,
+                                const std::shared_ptr<DeviceMap>& devices)
+{
+    std::set<size_t> foundList;
+
+    std::string path = "/sys/bus/i2c/devices/i2c-" + std::to_string(i2cBus);
+
+    // For each file listed under the i2c device
+    // NOTE: This should be faster than just checking for each possible address
+    // path.
+    auto ec = std::error_code();
+    for (const auto& p : fs::directory_iterator(path, ec))
+    {
+        if (ec)
+        {
+            std::cerr << "directory_iterator err " << ec.message() << "\n";
+            break;
+        }
+        const std::string node = p.path().string();
+        std::smatch m;
+        bool found =
+            std::regex_match(node, m, std::regex(".+\\d+-([0-9abcdef]+$)"));
+
+        if (!found)
+        {
+            continue;
+        }
+        if (m.size() != 2)
+        {
+            std::cerr << "regex didn't capture\n";
+            continue;
+        }
+
+        std::ssub_match subMatch = m[1];
+        std::string addressString = subMatch.str();
+        std::string_view addressStringView(addressString);
+
+        size_t address = 0;
+        std::from_chars(addressStringView.begin(), addressStringView.end(),
+                        address, 16);
+
+        const std::string eeprom = node + "/eeprom";
+
+        try
+        {
+            if (!fs::exists(eeprom))
+            {
+                continue;
+            }
+        }
+        catch (...)
+        {
+            continue;
+        }
+
+        // There is an eeprom file at this address, it may have invalid
+        // contents, but we found it.
+        foundList.insert(address);
+
+        std::vector<uint8_t> device = processEeprom(i2cBus, address);
+        if (!device.empty())
+        {
+            devices->emplace(address, device);
+        }
+    }
+
+    return foundList;
+}
+
+int getBusFRUs(int file, int first, int last, int bus,
+               std::shared_ptr<DeviceMap> devices, const bool& powerIsOn,
+               sdbusplus::asio::object_server& objServer)
+{
+    std::future<int> future = std::async(std::launch::async, [&]() {
+        // NOTE: When reading the devices raw on the bus, it can interfere with
+        // the driver's ability to operate, therefore read eeproms first before
+        // scanning for devices without drivers. Several experiments were run
+        // and it was determined that if there were any devices on the bus
+        // before the eeprom was hit and read, the eeprom driver wouldn't open
+        // while the bus device was open. An experiment was not performed to see
+        // if this issue was resolved if the i2c bus device was closed, but
+        // hexdumps of the eeprom later were successful.
+
+        // Scan for i2c eeproms loaded on this bus.
+        std::set<size_t> skipList = findI2CEeproms(bus, devices);
+        std::set<size_t>& failedItems = failedAddresses[bus];
+        std::set<size_t>& foundItems = fruAddresses[bus];
+        foundItems.clear();
+
+        auto busFind = busBlocklist.find(bus);
+        if (busFind != busBlocklist.end())
+        {
+            if (busFind->second != std::nullopt)
+            {
+                for (const auto& address : *(busFind->second))
+                {
+                    skipList.insert(address);
+                }
+            }
+        }
+
+        std::set<size_t>* rootFailures = nullptr;
+        int rootBus = getRootBus(bus);
+
+        if (rootBus >= 0)
+        {
+            auto rootBusFind = busBlocklist.find(rootBus);
+            if (rootBusFind != busBlocklist.end())
+            {
+                if (rootBusFind->second != std::nullopt)
+                {
+                    for (const auto& rootAddress : *(rootBusFind->second))
+                    {
+                        skipList.insert(rootAddress);
+                    }
+                }
+            }
+            rootFailures = &(failedAddresses[rootBus]);
+            foundItems = fruAddresses[rootBus];
+        }
+
+        constexpr int startSkipTargetAddr = 0;
+        constexpr int endSkipTargetAddr = 12;
+
+        for (int ii = first; ii <= last; ii++)
+        {
+            if (foundItems.find(ii) != foundItems.end())
+            {
+                continue;
+            }
+            if (skipList.find(ii) != skipList.end())
+            {
+                continue;
+            }
+            // skipping since no device is present in this range
+            if (ii >= startSkipTargetAddr && ii <= endSkipTargetAddr)
+            {
+                continue;
+            }
+            // Set target address
+            if (ioctl(file, I2C_SLAVE, ii) < 0)
+            {
+                std::cerr << "device at bus " << bus << " address " << ii
+                          << " busy\n";
+                continue;
+            }
+            // probe
+            if (i2c_smbus_read_byte(file) < 0)
+            {
+                continue;
+            }
+
+            lg2::debug("something at bus {BUS}, addr {ADDR}", "BUS", bus,
+                       "ADDR", ii);
+
+            makeProbeInterface(bus, ii, objServer);
+
+            if (failedItems.find(ii) != failedItems.end())
+            {
+                // if we failed to read it once, unlikely we can read it later
+                continue;
+            }
+
+            if (rootFailures != nullptr)
+            {
+                if (rootFailures->find(ii) != rootFailures->end())
+                {
+                    continue;
+                }
+            }
+
+            /* Check for Device type if it is 8 bit or 16 bit */
+            std::optional<bool> is16Bit = isDevice16Bit(file, ii);
+            if (!is16Bit.has_value())
+            {
+                std::cerr << "failed to read bus " << bus << " address " << ii
+                          << "\n";
+                if (powerIsOn)
+                {
+                    failedItems.insert(ii);
+                }
+                continue;
+            }
+            bool is16BitBool{*is16Bit};
+
+            auto readFunc = [is16BitBool, file,
+                             ii](off_t offset, size_t length, uint8_t* outbuf) {
+                return readData(is16BitBool, false, file, ii, offset, length,
+                                outbuf);
+            };
+            FRUReader reader(std::move(readFunc));
+            std::string errorMessage =
+                "bus " + std::to_string(bus) + " address " + std::to_string(ii);
+            std::pair<std::vector<uint8_t>, bool> pair =
+                readFRUContents(reader, errorMessage);
+            const bool foundHeader = pair.second;
+
+            if (!foundHeader && !is16BitBool)
+            {
+                // certain FRU eeproms require bytewise reading.
+                // otherwise garbage is read. e.g. SuperMicro PWS 920P-SQ
+
+                auto readFunc =
+                    [is16BitBool, file,
+                     ii](off_t offset, size_t length, uint8_t* outbuf) {
+                        return readData(is16BitBool, true, file, ii, offset,
+                                        length, outbuf);
+                    };
+                FRUReader readerBytewise(std::move(readFunc));
+                pair = readFRUContents(readerBytewise, errorMessage);
+            }
+
+            if (pair.first.empty())
+            {
+                continue;
+            }
+
+            devices->emplace(ii, pair.first);
+            fruAddresses[bus].insert(ii);
+        }
+        return 1;
+    });
+    std::future_status status =
+        future.wait_for(std::chrono::seconds(busTimeoutSeconds));
+    if (status == std::future_status::timeout)
+    {
+        std::cerr << "Error reading bus " << bus << "\n";
+        if (powerIsOn)
+        {
+            busBlocklist[bus] = std::nullopt;
+        }
+        close(file);
+        return -1;
+    }
+
+    close(file);
+    return future.get();
+}
+
+void loadBlocklist(const char* path)
+{
+    std::ifstream blocklistStream(path);
+    if (!blocklistStream.good())
+    {
+        // File is optional.
+        std::cerr << "Cannot open blocklist file.\n\n";
+        return;
+    }
+
+    nlohmann::json data =
+        nlohmann::json::parse(blocklistStream, nullptr, false);
+    if (data.is_discarded())
+    {
+        std::cerr << "Illegal blocklist file detected, cannot validate JSON, "
+                     "exiting\n";
+        std::exit(EXIT_FAILURE);
+    }
+
+    // It's expected to have at least one field, "buses" that is an array of the
+    // buses by integer. Allow for future options to exclude further aspects,
+    // such as specific addresses or ranges.
+    if (data.type() != nlohmann::json::value_t::object)
+    {
+        std::cerr << "Illegal blocklist, expected to read dictionary\n";
+        std::exit(EXIT_FAILURE);
+    }
+
+    // If buses field is missing, that's fine.
+    if (data.count("buses") == 1)
+    {
+        // Parse the buses array after a little validation.
+        auto buses = data.at("buses");
+        if (buses.type() != nlohmann::json::value_t::array)
+        {
+            // Buses field present but invalid, therefore this is an error.
+            std::cerr << "Invalid contents for blocklist buses field\n";
+            std::exit(EXIT_FAILURE);
+        }
+
+        // Catch exception here for type mis-match.
+        try
+        {
+            for (const auto& busIterator : buses)
+            {
+                // If bus and addresses field are missing, that's fine.
+                if (busIterator.contains("bus") &&
+                    busIterator.contains("addresses"))
+                {
+                    auto busData = busIterator.at("bus");
+                    auto bus = busData.get<size_t>();
+
+                    auto addressData = busIterator.at("addresses");
+                    auto addresses =
+                        addressData.get<std::set<std::string_view>>();
+
+                    auto& block = busBlocklist[bus].emplace();
+                    for (const auto& address : addresses)
+                    {
+                        size_t addressInt = 0;
+                        std::from_chars(address.begin() + 2, address.end(),
+                                        addressInt, 16);
+                        block.insert(addressInt);
+                    }
+                }
+                else
+                {
+                    busBlocklist[busIterator.get<size_t>()] = std::nullopt;
+                }
+            }
+        }
+        catch (const nlohmann::detail::type_error& e)
+        {
+            // Type mis-match is a critical error.
+            std::cerr << "Invalid bus type: " << e.what() << "\n";
+            std::exit(EXIT_FAILURE);
+        }
+    }
+}
+
+static void findI2CDevices(const std::vector<fs::path>& i2cBuses,
+                           BusMap& busmap, const bool& powerIsOn,
+                           sdbusplus::asio::object_server& objServer)
+{
+    for (const auto& i2cBus : i2cBuses)
+    {
+        int bus = busStrToInt(i2cBus.string());
+
+        if (bus < 0)
+        {
+            std::cerr << "Cannot translate " << i2cBus << " to int\n";
+            continue;
+        }
+        auto busFind = busBlocklist.find(bus);
+        if (busFind != busBlocklist.end())
+        {
+            if (busFind->second == std::nullopt)
+            {
+                continue; // Skip blocked busses.
+            }
+        }
+        int rootBus = getRootBus(bus);
+        auto rootBusFind = busBlocklist.find(rootBus);
+        if (rootBusFind != busBlocklist.end())
+        {
+            if (rootBusFind->second == std::nullopt)
+            {
+                continue;
+            }
+        }
+
+        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";
+            close(file);
+            continue;
+        }
+        if (((funcs & I2C_FUNC_SMBUS_READ_BYTE) == 0U) ||
+            ((I2C_FUNC_SMBUS_READ_I2C_BLOCK) == 0))
+        {
+            std::cerr << "Error: Can't use SMBus Receive Byte command bus "
+                      << bus << "\n";
+            close(file);
+            continue;
+        }
+        auto& device = busmap[bus];
+        device = std::make_shared<DeviceMap>();
+
+        //  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.
+        lg2::debug("Scanning bus {BUS}", "BUS", bus);
+
+        // fd is closed in this function in case the bus locks up
+        getBusFRUs(file, 0x03, 0x77, bus, device, powerIsOn, objServer);
+
+        lg2::debug("Done scanning bus {BUS}", "BUS", bus);
+    }
+}
+
+// this class allows an async response after all i2c devices are discovered
+struct FindDevicesWithCallback :
+    std::enable_shared_from_this<FindDevicesWithCallback>
+{
+    FindDevicesWithCallback(const std::vector<fs::path>& i2cBuses,
+                            BusMap& busmap, const bool& powerIsOn,
+                            sdbusplus::asio::object_server& objServer,
+                            std::function<void()>&& callback) :
+        _i2cBuses(i2cBuses), _busMap(busmap), _powerIsOn(powerIsOn),
+        _objServer(objServer), _callback(std::move(callback))
+    {}
+    ~FindDevicesWithCallback()
+    {
+        _callback();
+    }
+    void run()
+    {
+        findI2CDevices(_i2cBuses, _busMap, _powerIsOn, _objServer);
+    }
+
+    const std::vector<fs::path>& _i2cBuses;
+    BusMap& _busMap;
+    const bool& _powerIsOn;
+    sdbusplus::asio::object_server& _objServer;
+    std::function<void()> _callback;
+};
+
+void addFruObjectToDbus(
+    std::vector<uint8_t>& device,
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    uint32_t bus, uint32_t address, size_t& unknownBusObjectCount,
+    const bool& powerIsOn, sdbusplus::asio::object_server& objServer,
+    std::shared_ptr<sdbusplus::asio::connection>& systemBus)
+{
+    boost::container::flat_map<std::string, std::string> formattedFRU;
+
+    std::optional<std::string> optionalProductName = getProductName(
+        device, formattedFRU, bus, address, unknownBusObjectCount);
+    if (!optionalProductName)
+    {
+        std::cerr << "getProductName failed. product name is empty.\n";
+        return;
+    }
+
+    std::string productName =
+        "/xyz/openbmc_project/FruDevice/" + optionalProductName.value();
+
+    std::optional<int> index = findIndexForFRU(dbusInterfaceMap, productName);
+    if (index.has_value())
+    {
+        productName += "_";
+        productName += std::to_string(++(*index));
+    }
+
+    std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
+        objServer.add_interface(productName, "xyz.openbmc_project.FruDevice");
+    dbusInterfaceMap[std::pair<size_t, size_t>(bus, address)] = iface;
+
+    for (auto& property : formattedFRU)
+    {
+        std::regex_replace(property.second.begin(), property.second.begin(),
+                           property.second.end(), nonAsciiRegex, "_");
+        if (property.second.empty() && property.first != "PRODUCT_ASSET_TAG")
+        {
+            continue;
+        }
+        std::string key =
+            std::regex_replace(property.first, nonAsciiRegex, "_");
+
+        if (property.first == "PRODUCT_ASSET_TAG")
+        {
+            std::string propertyName = property.first;
+            iface->register_property(
+                key, property.second + '\0',
+                [bus, address, propertyName, &dbusInterfaceMap,
+                 &unknownBusObjectCount, &powerIsOn, &objServer,
+                 &systemBus](const std::string& req, std::string& resp) {
+                    if (strcmp(req.c_str(), resp.c_str()) != 0)
+                    {
+                        // call the method which will update
+                        if (updateFRUProperty(req, bus, address, propertyName,
+                                              dbusInterfaceMap,
+                                              unknownBusObjectCount, powerIsOn,
+                                              objServer, systemBus))
+                        {
+                            resp = req;
+                        }
+                        else
+                        {
+                            throw std::invalid_argument(
+                                "FRU property update failed.");
+                        }
+                    }
+                    return 1;
+                });
+        }
+        else if (!iface->register_property(key, property.second + '\0'))
+        {
+            std::cerr << "illegal key: " << key << "\n";
+        }
+        lg2::debug("parsed FRU property: {FIRST}: {SECOND}", "FIRST",
+                   property.first, "SECOND", property.second);
+    }
+
+    // baseboard will be 0, 0
+    iface->register_property("BUS", bus);
+    iface->register_property("ADDRESS", address);
+
+    iface->initialize();
+}
+
+static bool readBaseboardFRU(std::vector<uint8_t>& baseboardFRU)
+{
+    // try to read baseboard fru from file
+    std::ifstream baseboardFRUFile(baseboardFruLocation, std::ios::binary);
+    if (baseboardFRUFile.good())
+    {
+        baseboardFRUFile.seekg(0, std::ios_base::end);
+        size_t fileSize = static_cast<size_t>(baseboardFRUFile.tellg());
+        baseboardFRU.resize(fileSize);
+        baseboardFRUFile.seekg(0, std::ios_base::beg);
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+        char* charOffset = reinterpret_cast<char*>(baseboardFRU.data());
+        baseboardFRUFile.read(charOffset, fileSize);
+    }
+    else
+    {
+        return false;
+    }
+    return true;
+}
+
+bool writeFRU(uint8_t bus, uint8_t address, const std::vector<uint8_t>& fru)
+{
+    boost::container::flat_map<std::string, std::string> tmp;
+    if (fru.size() > maxFruSize)
+    {
+        std::cerr << "Invalid fru.size() during writeFRU\n";
+        return false;
+    }
+    // verify legal fru by running it through fru parsing logic
+    if (formatIPMIFRU(fru, tmp) != resCodes::resOK)
+    {
+        std::cerr << "Invalid fru format during writeFRU\n";
+        return false;
+    }
+    // baseboard fru
+    if (bus == 0 && address == 0)
+    {
+        std::ofstream file(baseboardFruLocation, std::ios_base::binary);
+        if (!file.good())
+        {
+            std::cerr << "Error opening file " << baseboardFruLocation << "\n";
+            throw DBusInternalError();
+            return false;
+        }
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+        const char* charOffset = reinterpret_cast<const char*>(fru.data());
+        file.write(charOffset, fru.size());
+        return file.good();
+    }
+
+    if (hasEepromFile(bus, address))
+    {
+        auto path = getEepromPath(bus, address);
+        off_t offset = 0;
+
+        int eeprom = open(path.c_str(), O_RDWR | O_CLOEXEC);
+        if (eeprom < 0)
+        {
+            std::cerr << "unable to open i2c device " << path << "\n";
+            throw DBusInternalError();
+            return false;
+        }
+
+        std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
+        std::string errorMessage = "eeprom at " + std::to_string(bus) +
+                                   " address " + std::to_string(address);
+        auto readFunc = [eeprom](off_t offset, size_t length, uint8_t* outbuf) {
+            return readFromEeprom(eeprom, offset, length, outbuf);
+        };
+        FRUReader reader(std::move(readFunc));
+
+        if (!findFRUHeader(reader, errorMessage, blockData, offset))
+        {
+            offset = 0;
+        }
+
+        if (lseek(eeprom, offset, SEEK_SET) < 0)
+        {
+            std::cerr << "Unable to seek to offset " << offset
+                      << " in device: " << path << "\n";
+            close(eeprom);
+            throw DBusInternalError();
+        }
+
+        ssize_t writtenBytes = write(eeprom, fru.data(), fru.size());
+        if (writtenBytes < 0)
+        {
+            std::cerr << "unable to write to i2c device " << path << "\n";
+            close(eeprom);
+            throw DBusInternalError();
+            return false;
+        }
+
+        close(eeprom);
+        return true;
+    }
+
+    std::string i2cBus = "/dev/i2c-" + std::to_string(bus);
+
+    int file = open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
+    if (file < 0)
+    {
+        std::cerr << "unable to open i2c device " << i2cBus << "\n";
+        throw DBusInternalError();
+        return false;
+    }
+    if (ioctl(file, I2C_SLAVE_FORCE, address) < 0)
+    {
+        std::cerr << "unable to set device address\n";
+        close(file);
+        throw DBusInternalError();
+        return false;
+    }
+
+    constexpr const size_t retryMax = 2;
+    uint16_t index = 0;
+    size_t retries = retryMax;
+    while (index < fru.size())
+    {
+        if (((index != 0U) && ((index % (maxEepromPageIndex + 1)) == 0)) &&
+            (retries == retryMax))
+        {
+            // The 4K EEPROM only uses the A2 and A1 device address bits
+            // with the third bit being a memory page address bit.
+            if (ioctl(file, I2C_SLAVE_FORCE, ++address) < 0)
+            {
+                std::cerr << "unable to set device address\n";
+                close(file);
+                throw DBusInternalError();
+                return false;
+            }
+        }
+
+        if (i2c_smbus_write_byte_data(file, static_cast<uint8_t>(index),
+                                      fru[index]) < 0)
+        {
+            if ((retries--) == 0U)
+            {
+                std::cerr << "error writing fru: " << strerror(errno) << "\n";
+                close(file);
+                throw DBusInternalError();
+                return false;
+            }
+        }
+        else
+        {
+            retries = retryMax;
+            index++;
+        }
+        // most eeproms require 5-10ms between writes
+        std::this_thread::sleep_for(std::chrono::milliseconds(10));
+    }
+    close(file);
+    return true;
+}
+
+void rescanOneBus(
+    BusMap& busmap, uint16_t busNum,
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    bool dbusCall, size_t& unknownBusObjectCount, const bool& powerIsOn,
+    sdbusplus::asio::object_server& objServer,
+    std::shared_ptr<sdbusplus::asio::connection>& systemBus)
+{
+    for (auto device = foundDevices.begin(); device != foundDevices.end();)
+    {
+        if (device->first.first == static_cast<size_t>(busNum))
+        {
+            objServer.remove_interface(device->second);
+            device = foundDevices.erase(device);
+        }
+        else
+        {
+            device++;
+        }
+    }
+
+    fs::path busPath = fs::path("/dev/i2c-" + std::to_string(busNum));
+    if (!fs::exists(busPath))
+    {
+        if (dbusCall)
+        {
+            std::cerr << "Unable to access i2c bus " << static_cast<int>(busNum)
+                      << "\n";
+            throw std::invalid_argument("Invalid Bus.");
+        }
+        return;
+    }
+
+    std::vector<fs::path> i2cBuses;
+    i2cBuses.emplace_back(busPath);
+
+    auto scan = std::make_shared<FindDevicesWithCallback>(
+        i2cBuses, busmap, powerIsOn, objServer,
+        [busNum, &busmap, &dbusInterfaceMap, &unknownBusObjectCount, &powerIsOn,
+         &objServer, &systemBus]() {
+            for (auto busIface = dbusInterfaceMap.begin();
+                 busIface != dbusInterfaceMap.end();)
+            {
+                if (busIface->first.first == static_cast<size_t>(busNum))
+                {
+                    objServer.remove_interface(busIface->second);
+                    busIface = dbusInterfaceMap.erase(busIface);
+                }
+                else
+                {
+                    busIface++;
+                }
+            }
+            auto found = busmap.find(busNum);
+            if (found == busmap.end() || found->second == nullptr)
+            {
+                return;
+            }
+            for (auto& device : *(found->second))
+            {
+                addFruObjectToDbus(device.second, dbusInterfaceMap,
+                                   static_cast<uint32_t>(busNum), device.first,
+                                   unknownBusObjectCount, powerIsOn, objServer,
+                                   systemBus);
+            }
+        });
+    scan->run();
+}
+
+void rescanBusses(
+    BusMap& busmap,
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    size_t& unknownBusObjectCount, const bool& powerIsOn,
+    sdbusplus::asio::object_server& objServer,
+    std::shared_ptr<sdbusplus::asio::connection>& systemBus)
+{
+    static boost::asio::steady_timer timer(io);
+    timer.expires_after(std::chrono::seconds(1));
+
+    // setup an async wait in case we get flooded with requests
+    timer.async_wait([&](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            return;
+        }
+
+        if (ec)
+        {
+            std::cerr << "Error in timer: " << ec.message() << "\n";
+            return;
+        }
+
+        auto devDir = fs::path("/dev/");
+        std::vector<fs::path> i2cBuses;
+
+        boost::container::flat_map<size_t, fs::path> busPaths;
+        if (!getI2cDevicePaths(devDir, busPaths))
+        {
+            std::cerr << "unable to find i2c devices\n";
+            return;
+        }
+
+        for (const auto& busPath : busPaths)
+        {
+            i2cBuses.emplace_back(busPath.second);
+        }
+
+        busmap.clear();
+        for (auto& [pair, interface] : foundDevices)
+        {
+            objServer.remove_interface(interface);
+        }
+        foundDevices.clear();
+
+        auto scan = std::make_shared<FindDevicesWithCallback>(
+            i2cBuses, busmap, powerIsOn, objServer, [&]() {
+                for (auto& busIface : dbusInterfaceMap)
+                {
+                    objServer.remove_interface(busIface.second);
+                }
+
+                dbusInterfaceMap.clear();
+                unknownBusObjectCount = 0;
+
+                // todo, get this from a more sensable place
+                std::vector<uint8_t> baseboardFRU;
+                if (readBaseboardFRU(baseboardFRU))
+                {
+                    // If no device on i2c bus 0, the insertion will happen.
+                    auto bus0 =
+                        busmap.try_emplace(0, std::make_shared<DeviceMap>());
+                    bus0.first->second->emplace(0, baseboardFRU);
+                }
+                for (auto& devicemap : busmap)
+                {
+                    for (auto& device : *devicemap.second)
+                    {
+                        addFruObjectToDbus(device.second, dbusInterfaceMap,
+                                           devicemap.first, device.first,
+                                           unknownBusObjectCount, powerIsOn,
+                                           objServer, systemBus);
+                    }
+                }
+            });
+        scan->run();
+    });
+}
+
+// Details with example of Asset Tag Update
+// To find location of Product Info Area asset tag as per FRU specification
+// 1. Find product Info area starting offset (*8 - as header will be in
+// multiple of 8 bytes).
+// 2. Skip 3 bytes of product info area (like format version, area length,
+// and language code).
+// 3. Traverse manufacturer name, product name, product version, & product
+// serial number, by reading type/length code to reach the Asset Tag.
+// 4. Update the Asset Tag, reposition the product Info area in multiple of
+// 8 bytes. Update the Product area length and checksum.
+
+bool updateFRUProperty(
+    const std::string& updatePropertyReq, uint32_t bus, uint32_t address,
+    const std::string& propertyName,
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    size_t& unknownBusObjectCount, const bool& powerIsOn,
+    sdbusplus::asio::object_server& objServer,
+    std::shared_ptr<sdbusplus::asio::connection>& systemBus)
+{
+    size_t updatePropertyReqLen = updatePropertyReq.length();
+    if (updatePropertyReqLen == 1 || updatePropertyReqLen > 63)
+    {
+        std::cerr
+            << "FRU field data cannot be of 1 char or more than 63 chars. "
+               "Invalid Length "
+            << updatePropertyReqLen << "\n";
+        return false;
+    }
+
+    std::vector<uint8_t> fruData;
+
+    if (!getFruData(fruData, bus, address))
+    {
+        std::cerr << "Failure getting FRU Data \n";
+        return false;
+    }
+
+    struct FruArea fruAreaParams{};
+
+    if (!findFruAreaLocationAndField(fruData, propertyName, fruAreaParams))
+    {
+        std::cerr << "findFruAreaLocationAndField failed \n";
+        return false;
+    }
+
+    std::vector<uint8_t> restFRUAreaFieldsData;
+    if (!copyRestFRUArea(fruData, propertyName, fruAreaParams,
+                         restFRUAreaFieldsData))
+    {
+        std::cerr << "copyRestFRUArea failed \n";
+        return false;
+    }
+
+    // Push post update fru areas if any
+    unsigned int nextFRUAreaLoc = 0;
+    for (fruAreas nextFRUArea = fruAreas::fruAreaInternal;
+         nextFRUArea <= fruAreas::fruAreaMultirecord; ++nextFRUArea)
+    {
+        unsigned int fruAreaLoc =
+            fruData[getHeaderAreaFieldOffset(nextFRUArea)] * fruBlockSize;
+        if ((fruAreaLoc > fruAreaParams.restFieldsEnd) &&
+            ((nextFRUAreaLoc == 0) || (fruAreaLoc < nextFRUAreaLoc)))
+        {
+            nextFRUAreaLoc = fruAreaLoc;
+        }
+    }
+    std::vector<uint8_t> restFRUAreasData;
+    if (nextFRUAreaLoc != 0U)
+    {
+        std::copy_n(fruData.begin() + nextFRUAreaLoc,
+                    fruData.size() - nextFRUAreaLoc,
+                    std::back_inserter(restFRUAreasData));
+    }
+
+    // check FRU area size
+    size_t fruAreaDataSize =
+        ((fruAreaParams.updateFieldLoc - fruAreaParams.start + 1) +
+         restFRUAreaFieldsData.size());
+    size_t fruAreaAvailableSize = fruAreaParams.size - fruAreaDataSize;
+    if ((updatePropertyReqLen + 1) > fruAreaAvailableSize)
+    {
+#ifdef ENABLE_FRU_AREA_RESIZE
+        size_t newFRUAreaSize = fruAreaDataSize + updatePropertyReqLen + 1;
+        // round size to 8-byte blocks
+        newFRUAreaSize =
+            ((newFRUAreaSize - 1) / fruBlockSize + 1) * fruBlockSize;
+        size_t newFRUDataSize =
+            fruData.size() + newFRUAreaSize - fruAreaParams.size;
+        fruData.resize(newFRUDataSize);
+        fruAreaParams.size = newFRUAreaSize;
+        fruAreaParams.end = fruAreaParams.start + fruAreaParams.size;
+#else
+        std::cerr << "FRU field length: " << updatePropertyReqLen + 1
+                  << " should not be greater than available FRU area size: "
+                  << fruAreaAvailableSize << "\n";
+        return false;
+#endif // ENABLE_FRU_AREA_RESIZE
+    }
+
+    // write new requested property field length and data
+    constexpr uint8_t newTypeLenMask = 0xC0;
+    fruData[fruAreaParams.updateFieldLoc] =
+        static_cast<uint8_t>(updatePropertyReqLen | newTypeLenMask);
+    fruAreaParams.updateFieldLoc++;
+    std::copy(updatePropertyReq.begin(), updatePropertyReq.end(),
+              fruData.begin() + fruAreaParams.updateFieldLoc);
+
+    // Copy remaining data to main fru area - post updated fru field vector
+    fruAreaParams.restFieldsLoc =
+        fruAreaParams.updateFieldLoc + updatePropertyReqLen;
+    size_t fruAreaDataEnd =
+        fruAreaParams.restFieldsLoc + restFRUAreaFieldsData.size();
+
+    std::copy(restFRUAreaFieldsData.begin(), restFRUAreaFieldsData.end(),
+              fruData.begin() + fruAreaParams.restFieldsLoc);
+
+    // Update final fru with new fru area length and checksum
+    unsigned int nextFRUAreaNewLoc = updateFRUAreaLenAndChecksum(
+        fruData, fruAreaParams.start, fruAreaDataEnd, fruAreaParams.end);
+
+#ifdef ENABLE_FRU_AREA_RESIZE
+    ++nextFRUAreaNewLoc;
+    ssize_t nextFRUAreaOffsetDiff =
+        (nextFRUAreaNewLoc - nextFRUAreaLoc) / fruBlockSize;
+    // Append rest FRU Areas if size changed and there were other sections after
+    // updated one
+    if (nextFRUAreaOffsetDiff && nextFRUAreaLoc)
+    {
+        std::copy(restFRUAreasData.begin(), restFRUAreasData.end(),
+                  fruData.begin() + nextFRUAreaNewLoc);
+        // Update Common Header
+        for (fruAreas nextFRUArea = fruAreas::fruAreaInternal;
+             nextFRUArea <= fruAreas::fruAreaMultirecord; ++nextFRUArea)
+        {
+            unsigned int fruAreaOffsetField =
+                getHeaderAreaFieldOffset(nextFRUArea);
+            size_t curFRUAreaOffset = fruData[fruAreaOffsetField];
+            if (curFRUAreaOffset > fruAreaParams.end)
+            {
+                fruData[fruAreaOffsetField] = static_cast<int8_t>(
+                    curFRUAreaOffset + nextFRUAreaOffsetDiff);
+            }
+        }
+        // Calculate new checksum
+        std::vector<uint8_t> headerFRUData;
+        std::copy_n(fruData.begin(), 7, std::back_inserter(headerFRUData));
+        size_t checksumVal = calculateChecksum(headerFRUData);
+        fruData[7] = static_cast<uint8_t>(checksumVal);
+        // fill zeros if FRU Area size decreased
+        if (nextFRUAreaOffsetDiff < 0)
+        {
+            std::fill(fruData.begin() + nextFRUAreaNewLoc +
+                          restFRUAreasData.size(),
+                      fruData.end(), 0);
+        }
+    }
+#else
+    // this is to avoid "unused variable" warning
+    (void)nextFRUAreaNewLoc;
+#endif // ENABLE_FRU_AREA_RESIZE
+    if (fruData.empty())
+    {
+        return false;
+    }
+
+    if (!writeFRU(static_cast<uint8_t>(bus), static_cast<uint8_t>(address),
+                  fruData))
+    {
+        return false;
+    }
+
+    // Rescan the bus so that GetRawFru dbus-call fetches updated values
+    rescanBusses(busMap, dbusInterfaceMap, unknownBusObjectCount, powerIsOn,
+                 objServer, systemBus);
+    return true;
+}
+
+int main()
+{
+    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+    sdbusplus::asio::object_server objServer(systemBus);
+
+    static size_t unknownBusObjectCount = 0;
+    static bool powerIsOn = false;
+    auto devDir = fs::path("/dev/");
+    auto matchString = std::string(R"(i2c-\d+$)");
+    std::vector<fs::path> i2cBuses;
+
+    if (!findFiles(devDir, matchString, i2cBuses))
+    {
+        std::cerr << "unable to find i2c devices\n";
+        return 1;
+    }
+
+    // check for and load blocklist with initial buses.
+    loadBlocklist(blocklistPath);
+
+    systemBus->request_name("xyz.openbmc_project.FruDevice");
+
+    // this is a map with keys of pair(bus number, address) and values of
+    // the object on dbus
+    boost::container::flat_map<std::pair<size_t, size_t>,
+                               std::shared_ptr<sdbusplus::asio::dbus_interface>>
+        dbusInterfaceMap;
+
+    std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
+        objServer.add_interface("/xyz/openbmc_project/FruDevice",
+                                "xyz.openbmc_project.FruDeviceManager");
+
+    iface->register_method("ReScan", [&]() {
+        rescanBusses(busMap, dbusInterfaceMap, unknownBusObjectCount, powerIsOn,
+                     objServer, systemBus);
+    });
+
+    iface->register_method("ReScanBus", [&](uint16_t bus) {
+        rescanOneBus(busMap, bus, dbusInterfaceMap, true, unknownBusObjectCount,
+                     powerIsOn, objServer, systemBus);
+    });
+
+    iface->register_method("GetRawFru", getFRUInfo);
+
+    iface->register_method(
+        "WriteFru", [&](const uint16_t bus, const uint8_t address,
+                        const std::vector<uint8_t>& data) {
+            if (!writeFRU(bus, address, data))
+            {
+                throw std::invalid_argument("Invalid Arguments.");
+                return;
+            }
+            // schedule rescan on success
+            rescanBusses(busMap, dbusInterfaceMap, unknownBusObjectCount,
+                         powerIsOn, objServer, systemBus);
+        });
+    iface->initialize();
+
+    std::function<void(sdbusplus::message_t & message)> eventHandler =
+        [&](sdbusplus::message_t& message) {
+            std::string objectName;
+            boost::container::flat_map<
+                std::string,
+                std::variant<std::string, bool, int64_t, uint64_t, double>>
+                values;
+            message.read(objectName, values);
+            auto findState = values.find("CurrentHostState");
+            if (findState != values.end())
+            {
+                if (std::get<std::string>(findState->second) ==
+                    "xyz.openbmc_project.State.Host.HostState.Running")
+                {
+                    powerIsOn = true;
+                }
+            }
+
+            if (powerIsOn)
+            {
+                rescanBusses(busMap, dbusInterfaceMap, unknownBusObjectCount,
+                             powerIsOn, objServer, systemBus);
+            }
+        };
+
+    sdbusplus::bus::match_t powerMatch = sdbusplus::bus::match_t(
+        static_cast<sdbusplus::bus_t&>(*systemBus),
+        "type='signal',interface='org.freedesktop.DBus.Properties',path='/xyz/"
+        "openbmc_project/state/"
+        "host0',arg0='xyz.openbmc_project.State.Host'",
+        eventHandler);
+
+    int fd = inotify_init();
+    inotify_add_watch(fd, i2CDevLocation, IN_CREATE | IN_MOVED_TO | IN_DELETE);
+    std::array<char, 4096> readBuffer{};
+    // monitor for new i2c devices
+    boost::asio::posix::stream_descriptor dirWatch(io, fd);
+    std::function<void(const boost::system::error_code, std::size_t)>
+        watchI2cBusses = [&](const boost::system::error_code& ec,
+                             std::size_t bytesTransferred) {
+            if (ec)
+            {
+                std::cout << "Callback Error " << ec << "\n";
+                return;
+            }
+            size_t index = 0;
+            while ((index + sizeof(inotify_event)) <= bytesTransferred)
+            {
+                const char* p = &readBuffer[index];
+                // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+                const auto* iEvent = reinterpret_cast<const inotify_event*>(p);
+                switch (iEvent->mask)
+                {
+                    case IN_CREATE:
+                    case IN_MOVED_TO:
+                    case IN_DELETE:
+                    {
+                        std::string_view name(&iEvent->name[0], iEvent->len);
+                        if (boost::starts_with(name, "i2c"))
+                        {
+                            int bus = busStrToInt(name);
+                            if (bus < 0)
+                            {
+                                std::cerr
+                                    << "Could not parse bus " << name << "\n";
+                                continue;
+                            }
+                            int rootBus = getRootBus(bus);
+                            if (rootBus >= 0)
+                            {
+                                rescanOneBus(busMap,
+                                             static_cast<uint16_t>(rootBus),
+                                             dbusInterfaceMap, false,
+                                             unknownBusObjectCount, powerIsOn,
+                                             objServer, systemBus);
+                            }
+                            rescanOneBus(busMap, static_cast<uint16_t>(bus),
+                                         dbusInterfaceMap, false,
+                                         unknownBusObjectCount, powerIsOn,
+                                         objServer, systemBus);
+                        }
+                    }
+                    break;
+                    default:
+                        break;
+                }
+                index += sizeof(inotify_event) + iEvent->len;
+            }
+
+            dirWatch.async_read_some(boost::asio::buffer(readBuffer),
+                                     watchI2cBusses);
+        };
+
+    dirWatch.async_read_some(boost::asio::buffer(readBuffer), watchI2cBusses);
+    // run the initial scan
+    rescanBusses(busMap, dbusInterfaceMap, unknownBusObjectCount, powerIsOn,
+                 objServer, systemBus);
+
+    io.run();
+    return 0;
+}
diff --git a/src/fru_device/fru_reader.cpp b/src/fru_device/fru_reader.cpp
new file mode 100644
index 0000000..61d4020
--- /dev/null
+++ b/src/fru_device/fru_reader.cpp
@@ -0,0 +1,91 @@
+/*
+// Copyright (c) 2022 Equinix, Inc.
+//
+// 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 "fru_reader.hpp"
+
+#include <cstring>
+
+ssize_t FRUReader::read(off_t start, size_t len, uint8_t* outbuf)
+{
+    size_t done = 0;
+    size_t remaining = len;
+    size_t cursor = start;
+    while (done < len)
+    {
+        if (eof.has_value() && cursor >= eof.value())
+        {
+            break;
+        }
+
+        const uint8_t* blkData = nullptr;
+        size_t available = 0;
+        size_t blk = cursor / cacheBlockSize;
+        size_t blkOffset = cursor % cacheBlockSize;
+        auto findBlk = cache.find(blk);
+        if (findBlk == cache.end())
+        {
+            // miss, populate cache
+            uint8_t* newData = cache[blk].data();
+            int64_t ret =
+                readFunc(blk * cacheBlockSize, cacheBlockSize, newData);
+
+            // if we've reached the end of the eeprom, record its size
+            if (ret >= 0 && static_cast<size_t>(ret) < cacheBlockSize)
+            {
+                eof = (blk * cacheBlockSize) + ret;
+            }
+
+            if (ret <= 0)
+            {
+                // don't leave empty blocks in the cache
+                cache.erase(blk);
+                return done != 0U ? done : ret;
+            }
+
+            blkData = newData;
+            available = ret;
+        }
+        else
+        {
+            // hit, use cached data
+            blkData = findBlk->second.data();
+
+            // if the hit is to the block containing the (previously
+            // discovered on the miss that populated it) end of the eeprom,
+            // don't copy spurious bytes past the end
+            if (eof.has_value() && (eof.value() / cacheBlockSize == blk))
+            {
+                available = eof.value() % cacheBlockSize;
+            }
+            else
+            {
+                available = cacheBlockSize;
+            }
+        }
+
+        size_t toCopy = (blkOffset >= available)
+                            ? 0
+                            : std::min(available - blkOffset, remaining);
+
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+        memcpy(outbuf + done, blkData + blkOffset, toCopy);
+        cursor += toCopy;
+        done += toCopy;
+        remaining -= toCopy;
+    }
+
+    return done;
+}
diff --git a/src/fru_device/fru_reader.hpp b/src/fru_device/fru_reader.hpp
new file mode 100644
index 0000000..4083be1
--- /dev/null
+++ b/src/fru_device/fru_reader.hpp
@@ -0,0 +1,63 @@
+/*
+// Copyright (c) 2022 Equinix, Inc.
+//
+// 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.
+*/
+
+#pragma once
+
+#include <cstdint>
+#include <cstdio>
+#include <functional>
+#include <map>
+#include <optional>
+#include <utility>
+
+extern "C"
+{
+// For I2C_SMBUS_BLOCK_MAX
+#include <linux/i2c.h>
+}
+
+// A function to read up to I2C_SMBUS_BLOCK_MAX bytes of FRU data.  Returns
+// negative on error, or the number of bytes read otherwise, which may be (but
+// is not guaranteed to be) less than len if the read would go beyond the end
+// of the FRU.
+using ReadBlockFunc =
+    std::function<int64_t(off_t offset, size_t len, uint8_t* outbuf)>;
+
+// A caching wrapper around a ReadBlockFunc
+class FRUReader
+{
+  public:
+    explicit FRUReader(ReadBlockFunc readFunc) : readFunc(std::move(readFunc))
+    {}
+    // The ::read() operation here is analogous to ReadBlockFunc (with the same
+    // return value semantics), but is not subject to SMBus block size
+    // limitations; it can read as much data as needed in a single call.
+    ssize_t read(off_t start, size_t len, uint8_t* outbuf);
+
+  private:
+    static constexpr size_t cacheBlockSize = 32;
+    static_assert(cacheBlockSize <= I2C_SMBUS_BLOCK_MAX);
+    using CacheBlock = std::array<uint8_t, cacheBlockSize>;
+
+    // indexed by block number (byte number / block size)
+    using Cache = std::map<uint32_t, CacheBlock>;
+
+    ReadBlockFunc readFunc;
+    Cache cache;
+
+    // byte offset of the end of the FRU (if readFunc has reported it)
+    std::optional<size_t> eof;
+};
diff --git a/src/fru_device/fru_utils.cpp b/src/fru_device/fru_utils.cpp
new file mode 100644
index 0000000..0a1f583
--- /dev/null
+++ b/src/fru_device/fru_utils.cpp
@@ -0,0 +1,1187 @@
+/*
+// 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 fru_utils.cpp
+
+#include "fru_utils.hpp"
+
+#include <phosphor-logging/lg2.hpp>
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <filesystem>
+#include <iomanip>
+#include <iostream>
+#include <numeric>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+extern "C"
+{
+// Include for I2C_SMBUS_BLOCK_MAX
+#include <linux/i2c.h>
+}
+
+constexpr size_t fruVersion = 1; // Current FRU spec version number is 1
+
+std::tm intelEpoch()
+{
+    std::tm val = {};
+    val.tm_year = 1996 - 1900;
+    val.tm_mday = 1;
+    return val;
+}
+
+char sixBitToChar(uint8_t val)
+{
+    return static_cast<char>((val & 0x3f) + ' ');
+}
+
+char bcdPlusToChar(uint8_t val)
+{
+    val &= 0xf;
+    return (val < 10) ? static_cast<char>(val + '0') : bcdHighChars[val - 10];
+}
+
+enum FRUDataEncoding
+{
+    binary = 0x0,
+    bcdPlus = 0x1,
+    sixBitASCII = 0x2,
+    languageDependent = 0x3,
+};
+
+enum MultiRecordType : uint8_t
+{
+    powerSupplyInfo = 0x00,
+    dcOutput = 0x01,
+    dcLoad = 0x02,
+    managementAccessRecord = 0x03,
+    baseCompatibilityRecord = 0x04,
+    extendedCompatibilityRecord = 0x05,
+    resvASFSMBusDeviceRecord = 0x06,
+    resvASFLegacyDeviceAlerts = 0x07,
+    resvASFRemoteControl = 0x08,
+    extendedDCOutput = 0x09,
+    extendedDCLoad = 0x0A
+};
+
+enum SubManagementAccessRecord : uint8_t
+{
+    systemManagementURL = 0x01,
+    systemName = 0x02,
+    systemPingAddress = 0x03,
+    componentManagementURL = 0x04,
+    componentName = 0x05,
+    componentPingAddress = 0x06,
+    systemUniqueID = 0x07
+};
+
+/* Decode FRU data into a std::string, given an input iterator and end. If the
+ * state returned is fruDataOk, then the resulting string is the decoded FRU
+ * data. The input iterator is advanced past the data consumed.
+ *
+ * On fruDataErr, we have lost synchronisation with the length bytes, so the
+ * iterator is no longer usable.
+ */
+std::pair<DecodeState, std::string> decodeFRUData(
+    std::span<const uint8_t>::const_iterator& iter,
+    std::span<const uint8_t>::const_iterator& end, bool isLangEng)
+{
+    std::string value;
+    unsigned int i = 0;
+
+    /* we need at least one byte to decode the type/len header */
+    if (iter == end)
+    {
+        std::cerr << "Truncated FRU data\n";
+        return make_pair(DecodeState::err, value);
+    }
+
+    uint8_t c = *(iter++);
+
+    /* 0xc1 is the end marker */
+    if (c == 0xc1)
+    {
+        return make_pair(DecodeState::end, value);
+    }
+
+    /* decode type/len byte */
+    uint8_t type = static_cast<uint8_t>(c >> 6);
+    uint8_t len = static_cast<uint8_t>(c & 0x3f);
+
+    /* we should have at least len bytes of data available overall */
+    if (iter + len > end)
+    {
+        std::cerr << "FRU data field extends past end of FRU area data\n";
+        return make_pair(DecodeState::err, value);
+    }
+
+    switch (type)
+    {
+        case FRUDataEncoding::binary:
+        {
+            std::stringstream ss;
+            ss << std::hex << std::setfill('0');
+            for (i = 0; i < len; i++, iter++)
+            {
+                uint8_t val = static_cast<uint8_t>(*iter);
+                ss << std::setw(2) << static_cast<int>(val);
+            }
+            value = ss.str();
+            break;
+        }
+        case FRUDataEncoding::languageDependent:
+            /* For language-code dependent encodings, assume 8-bit ASCII */
+            value = std::string(iter, iter + len);
+            iter += len;
+
+            /* English text is encoded in 8-bit ASCII + Latin 1. All other
+             * languages are required to use 2-byte unicode. FruDevice does not
+             * handle unicode.
+             */
+            if (!isLangEng)
+            {
+                std::cerr << "Error: Non english string is not supported \n";
+                return make_pair(DecodeState::err, value);
+            }
+
+            break;
+
+        case FRUDataEncoding::bcdPlus:
+            value = std::string();
+            for (i = 0; i < len; i++, iter++)
+            {
+                uint8_t val = *iter;
+                value.push_back(bcdPlusToChar(val >> 4));
+                value.push_back(bcdPlusToChar(val & 0xf));
+            }
+            break;
+
+        case FRUDataEncoding::sixBitASCII:
+        {
+            unsigned int accum = 0;
+            unsigned int accumBitLen = 0;
+            value = std::string();
+            for (i = 0; i < len; i++, iter++)
+            {
+                accum |= *iter << accumBitLen;
+                accumBitLen += 8;
+                while (accumBitLen >= 6)
+                {
+                    value.push_back(sixBitToChar(accum & 0x3f));
+                    accum >>= 6;
+                    accumBitLen -= 6;
+                }
+            }
+        }
+        break;
+
+        default:
+        {
+            return make_pair(DecodeState::err, value);
+        }
+    }
+
+    return make_pair(DecodeState::ok, value);
+}
+
+bool checkLangEng(uint8_t lang)
+{
+    // If Lang is not English then the encoding is defined as 2-byte UNICODE,
+    // but we don't support that.
+    if ((lang != 0U) && lang != 25)
+    {
+        std::cerr << "Warning: languages other than English is not "
+                     "supported\n";
+        // Return language flag as non english
+        return false;
+    }
+    return true;
+}
+
+/* This function verifies for other offsets to check if they are not
+ * falling under other field area
+ *
+ * fruBytes:    Start of Fru data
+ * currentArea: Index of current area offset to be compared against all area
+ *              offset and it is a multiple of 8 bytes as per specification
+ * len:         Length of current area space and it is a multiple of 8 bytes
+ *              as per specification
+ */
+bool verifyOffset(std::span<const uint8_t> fruBytes, fruAreas currentArea,
+                  uint8_t len)
+{
+    unsigned int fruBytesSize = fruBytes.size();
+
+    // check if Fru data has at least 8 byte header
+    if (fruBytesSize <= fruBlockSize)
+    {
+        std::cerr << "Error: trying to parse empty FRU\n";
+        return false;
+    }
+
+    // Check range of passed currentArea value
+    if (currentArea > fruAreas::fruAreaMultirecord)
+    {
+        std::cerr << "Error: Fru area is out of range\n";
+        return false;
+    }
+
+    unsigned int currentAreaIndex = getHeaderAreaFieldOffset(currentArea);
+    if (currentAreaIndex > fruBytesSize)
+    {
+        std::cerr << "Error: Fru area index is out of range\n";
+        return false;
+    }
+
+    unsigned int start = fruBytes[currentAreaIndex];
+    unsigned int end = start + len;
+
+    /* Verify each offset within the range of start and end */
+    for (fruAreas area = fruAreas::fruAreaInternal;
+         area <= fruAreas::fruAreaMultirecord; ++area)
+    {
+        // skip the current offset
+        if (area == currentArea)
+        {
+            continue;
+        }
+
+        unsigned int areaIndex = getHeaderAreaFieldOffset(area);
+        if (areaIndex > fruBytesSize)
+        {
+            std::cerr << "Error: Fru area index is out of range\n";
+            return false;
+        }
+
+        unsigned int areaOffset = fruBytes[areaIndex];
+        // if areaOffset is 0 means this area is not available so skip
+        if (areaOffset == 0)
+        {
+            continue;
+        }
+
+        // check for overlapping of current offset with given areaoffset
+        if (areaOffset == start || (areaOffset > start && areaOffset < end))
+        {
+            std::cerr << getFruAreaName(currentArea)
+                      << " offset is overlapping with " << getFruAreaName(area)
+                      << " offset\n";
+            return false;
+        }
+    }
+    return true;
+}
+
+static void parseMultirecordUUID(
+    std::span<const uint8_t> device,
+    boost::container::flat_map<std::string, std::string>& result)
+{
+    constexpr size_t uuidDataLen = 16;
+    constexpr size_t multiRecordHeaderLen = 5;
+    /* UUID record data, plus one to skip past the sub-record type byte */
+    constexpr size_t uuidRecordData = multiRecordHeaderLen + 1;
+    constexpr size_t multiRecordEndOfListMask = 0x80;
+    /* The UUID {00112233-4455-6677-8899-AABBCCDDEEFF} would thus be represented
+     * as: 0x33 0x22 0x11 0x00 0x55 0x44 0x77 0x66 0x88 0x99 0xAA 0xBB 0xCC 0xDD
+     * 0xEE 0xFF
+     */
+    const std::array<uint8_t, uuidDataLen> uuidCharOrder = {
+        3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15};
+    size_t offset = getHeaderAreaFieldOffset(fruAreas::fruAreaMultirecord);
+    if (offset >= device.size())
+    {
+        throw std::runtime_error("Multirecord UUID offset is out of range");
+    }
+    uint32_t areaOffset = device[offset];
+
+    if (areaOffset == 0)
+    {
+        return;
+    }
+
+    areaOffset *= fruBlockSize;
+    std::span<const uint8_t>::const_iterator fruBytesIter =
+        device.begin() + areaOffset;
+
+    /* Verify area offset */
+    if (!verifyOffset(device, fruAreas::fruAreaMultirecord, *fruBytesIter))
+    {
+        return;
+    }
+    while (areaOffset + uuidRecordData + uuidDataLen <= device.size())
+    {
+        if ((areaOffset < device.size()) &&
+            (device[areaOffset] ==
+             (uint8_t)MultiRecordType::managementAccessRecord))
+        {
+            if ((areaOffset + multiRecordHeaderLen < device.size()) &&
+                (device[areaOffset + multiRecordHeaderLen] ==
+                 (uint8_t)SubManagementAccessRecord::systemUniqueID))
+            {
+                /* Layout of UUID:
+                 * source: https://www.ietf.org/rfc/rfc4122.txt
+                 *
+                 * UUID binary format (16 bytes):
+                 * 4B-2B-2B-2B-6B (big endian)
+                 *
+                 * UUID string is 36 length of characters (36 bytes):
+                 * 0        9    14   19   24
+                 * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+                 *    be     be   be   be       be
+                 * be means it should be converted to big endian.
+                 */
+                /* Get UUID bytes to UUID string */
+                std::stringstream tmp;
+                tmp << std::hex << std::setfill('0');
+                for (size_t i = 0; i < uuidDataLen; i++)
+                {
+                    tmp << std::setw(2)
+                        << static_cast<uint16_t>(
+                               device[areaOffset + uuidRecordData +
+                                      uuidCharOrder[i]]);
+                }
+                std::string uuidStr = tmp.str();
+                result["MULTIRECORD_UUID"] =
+                    uuidStr.substr(0, 8) + '-' + uuidStr.substr(8, 4) + '-' +
+                    uuidStr.substr(12, 4) + '-' + uuidStr.substr(16, 4) + '-' +
+                    uuidStr.substr(20, 12);
+                break;
+            }
+        }
+        if ((device[areaOffset + 1] & multiRecordEndOfListMask) != 0)
+        {
+            break;
+        }
+        areaOffset = areaOffset + device[areaOffset + 2] + multiRecordHeaderLen;
+    }
+}
+
+resCodes decodeField(
+    std::span<const uint8_t>::const_iterator& fruBytesIter,
+    std::span<const uint8_t>::const_iterator& fruBytesIterEndArea,
+    const std::vector<std::string>& fruAreaFieldNames, size_t& fieldIndex,
+    DecodeState& state, bool isLangEng, const fruAreas& area,
+    boost::container::flat_map<std::string, std::string>& result)
+{
+    auto res = decodeFRUData(fruBytesIter, fruBytesIterEndArea, isLangEng);
+    state = res.first;
+    std::string value = res.second;
+    std::string name;
+    bool isCustomField = false;
+    if (fieldIndex < fruAreaFieldNames.size())
+    {
+        name = std::string(getFruAreaName(area)) + "_" +
+               fruAreaFieldNames.at(fieldIndex);
+    }
+    else
+    {
+        isCustomField = true;
+        name = std::string(getFruAreaName(area)) + "_" + fruCustomFieldName +
+               std::to_string(fieldIndex - fruAreaFieldNames.size() + 1);
+    }
+
+    if (state == DecodeState::ok)
+    {
+        // Strip non null characters and trailing spaces from the end
+        value.erase(
+            std::find_if(value.rbegin(), value.rend(),
+                         [](char ch) { return ((ch != 0) && (ch != ' ')); })
+                .base(),
+            value.end());
+        if (isCustomField)
+        {
+            // Some MAC addresses are stored in a custom field, with
+            // "MAC:" prefixed on the value.  If we see that, create a
+            // new field with the decoded data
+            if (value.starts_with("MAC: "))
+            {
+                result["MAC_" + name] = value.substr(5);
+            }
+        }
+        result[name] = std::move(value);
+        ++fieldIndex;
+    }
+    else if (state == DecodeState::err)
+    {
+        std::cerr << "Error while parsing " << name << "\n";
+
+        // Cancel decoding if failed to parse any of mandatory
+        // fields
+        if (fieldIndex < fruAreaFieldNames.size())
+        {
+            std::cerr << "Failed to parse mandatory field \n";
+            return resCodes::resErr;
+        }
+        return resCodes::resWarn;
+    }
+    else
+    {
+        if (fieldIndex < fruAreaFieldNames.size())
+        {
+            std::cerr << "Mandatory fields absent in FRU area "
+                      << getFruAreaName(area) << " after " << name << "\n";
+            return resCodes::resWarn;
+        }
+    }
+    return resCodes::resOK;
+}
+
+resCodes formatIPMIFRU(
+    std::span<const uint8_t> fruBytes,
+    boost::container::flat_map<std::string, std::string>& result)
+{
+    resCodes ret = resCodes::resOK;
+    if (fruBytes.size() <= fruBlockSize)
+    {
+        std::cerr << "Error: trying to parse empty FRU \n";
+        return resCodes::resErr;
+    }
+    result["Common_Format_Version"] =
+        std::to_string(static_cast<int>(*fruBytes.begin()));
+
+    const std::vector<std::string>* fruAreaFieldNames = nullptr;
+
+    // Don't parse Internal and Multirecord areas
+    for (fruAreas area = fruAreas::fruAreaChassis;
+         area <= fruAreas::fruAreaProduct; ++area)
+    {
+        size_t offset = *(fruBytes.begin() + getHeaderAreaFieldOffset(area));
+        if (offset == 0)
+        {
+            continue;
+        }
+        offset *= fruBlockSize;
+        std::span<const uint8_t>::const_iterator fruBytesIter =
+            fruBytes.begin() + offset;
+        if (fruBytesIter + fruBlockSize >= fruBytes.end())
+        {
+            std::cerr << "Not enough data to parse \n";
+            return resCodes::resErr;
+        }
+        // check for format version 1
+        if (*fruBytesIter != 0x01)
+        {
+            std::cerr << "Unexpected version " << *fruBytesIter << "\n";
+            return resCodes::resErr;
+        }
+        ++fruBytesIter;
+
+        /* Verify other area offset for overlap with current area by passing
+         * length of current area offset pointed by *fruBytesIter
+         */
+        if (!verifyOffset(fruBytes, area, *fruBytesIter))
+        {
+            return resCodes::resErr;
+        }
+
+        size_t fruAreaSize = *fruBytesIter * fruBlockSize;
+        std::span<const uint8_t>::const_iterator fruBytesIterEndArea =
+            fruBytes.begin() + offset + fruAreaSize - 1;
+        ++fruBytesIter;
+
+        uint8_t fruComputedChecksum =
+            calculateChecksum(fruBytes.begin() + offset, fruBytesIterEndArea);
+        if (fruComputedChecksum != *fruBytesIterEndArea)
+        {
+            std::stringstream ss;
+            ss << std::hex << std::setfill('0');
+            ss << "Checksum error in FRU area " << getFruAreaName(area) << "\n";
+            ss << "\tComputed checksum: 0x" << std::setw(2)
+               << static_cast<int>(fruComputedChecksum) << "\n";
+            ss << "\tThe read checksum: 0x" << std::setw(2)
+               << static_cast<int>(*fruBytesIterEndArea) << "\n";
+            std::cerr << ss.str();
+            ret = resCodes::resWarn;
+        }
+
+        /* Set default language flag to true as Chassis Fru area are always
+         * encoded in English defined in Section 10 of Fru specification
+         */
+
+        bool isLangEng = true;
+        switch (area)
+        {
+            case fruAreas::fruAreaChassis:
+            {
+                result["CHASSIS_TYPE"] =
+                    std::to_string(static_cast<int>(*fruBytesIter));
+                fruBytesIter += 1;
+                fruAreaFieldNames = &chassisFruAreas;
+                break;
+            }
+            case fruAreas::fruAreaBoard:
+            {
+                uint8_t lang = *fruBytesIter;
+                result["BOARD_LANGUAGE_CODE"] =
+                    std::to_string(static_cast<int>(lang));
+                isLangEng = checkLangEng(lang);
+                fruBytesIter += 1;
+
+                unsigned int minutes =
+                    *fruBytesIter | *(fruBytesIter + 1) << 8 |
+                    *(fruBytesIter + 2) << 16;
+                std::tm fruTime = intelEpoch();
+                std::time_t timeValue = timegm(&fruTime);
+                timeValue += static_cast<long>(minutes) * 60;
+                fruTime = *std::gmtime(&timeValue);
+
+                // Tue Nov 20 23:08:00 2018
+                std::array<char, 32> timeString = {};
+                auto bytes = std::strftime(timeString.data(), timeString.size(),
+                                           "%Y%m%dT%H%M%SZ", &fruTime);
+                if (bytes == 0)
+                {
+                    std::cerr << "invalid time string encountered\n";
+                    return resCodes::resErr;
+                }
+
+                result["BOARD_MANUFACTURE_DATE"] =
+                    std::string_view(timeString.data(), bytes);
+                fruBytesIter += 3;
+                fruAreaFieldNames = &boardFruAreas;
+                break;
+            }
+            case fruAreas::fruAreaProduct:
+            {
+                uint8_t lang = *fruBytesIter;
+                result["PRODUCT_LANGUAGE_CODE"] =
+                    std::to_string(static_cast<int>(lang));
+                isLangEng = checkLangEng(lang);
+                fruBytesIter += 1;
+                fruAreaFieldNames = &productFruAreas;
+                break;
+            }
+            default:
+            {
+                std::cerr << "Internal error: unexpected FRU area index: "
+                          << static_cast<int>(area) << " \n";
+                return resCodes::resErr;
+            }
+        }
+        size_t fieldIndex = 0;
+        DecodeState state = DecodeState::ok;
+        do
+        {
+            resCodes decodeRet = decodeField(fruBytesIter, fruBytesIterEndArea,
+                                             *fruAreaFieldNames, fieldIndex,
+                                             state, isLangEng, area, result);
+            if (decodeRet == resCodes::resErr)
+            {
+                return resCodes::resErr;
+            }
+            if (decodeRet == resCodes::resWarn)
+            {
+                ret = decodeRet;
+            }
+        } while (state == DecodeState::ok);
+        for (; fruBytesIter < fruBytesIterEndArea; fruBytesIter++)
+        {
+            uint8_t c = *fruBytesIter;
+            if (c != 0U)
+            {
+                std::cerr << "Non-zero byte after EndOfFields in FRU area "
+                          << getFruAreaName(area) << "\n";
+                ret = resCodes::resWarn;
+                break;
+            }
+        }
+    }
+
+    /* Parsing the Multirecord UUID */
+    parseMultirecordUUID(fruBytes, result);
+
+    return ret;
+}
+
+// Calculate new checksum for fru info area
+uint8_t calculateChecksum(std::span<const uint8_t>::const_iterator iter,
+                          std::span<const uint8_t>::const_iterator end)
+{
+    constexpr int checksumMod = 256;
+    uint8_t sum = std::accumulate(iter, end, static_cast<uint8_t>(0));
+    return (checksumMod - sum) % checksumMod;
+}
+
+uint8_t calculateChecksum(std::span<const uint8_t> fruAreaData)
+{
+    return calculateChecksum(fruAreaData.begin(), fruAreaData.end());
+}
+
+// Update new fru area length &
+// Update checksum at new checksum location
+// Return the offset of the area checksum byte
+unsigned int updateFRUAreaLenAndChecksum(
+    std::vector<uint8_t>& fruData, size_t fruAreaStart,
+    size_t fruAreaEndOfFieldsOffset, size_t fruAreaEndOffset)
+{
+    size_t traverseFRUAreaIndex = fruAreaEndOfFieldsOffset - fruAreaStart;
+
+    // fill zeros for any remaining unused space
+    std::fill(fruData.begin() + fruAreaEndOfFieldsOffset,
+              fruData.begin() + fruAreaEndOffset, 0);
+
+    size_t mod = traverseFRUAreaIndex % fruBlockSize;
+    size_t checksumLoc = 0;
+    if (mod == 0U)
+    {
+        traverseFRUAreaIndex += (fruBlockSize);
+        checksumLoc = fruAreaEndOfFieldsOffset + (fruBlockSize - 1);
+    }
+    else
+    {
+        traverseFRUAreaIndex += (fruBlockSize - mod);
+        checksumLoc = fruAreaEndOfFieldsOffset + (fruBlockSize - mod - 1);
+    }
+
+    size_t newFRUAreaLen =
+        (traverseFRUAreaIndex / fruBlockSize) +
+        static_cast<unsigned long>((traverseFRUAreaIndex % fruBlockSize) != 0);
+    size_t fruAreaLengthLoc = fruAreaStart + 1;
+    fruData[fruAreaLengthLoc] = static_cast<uint8_t>(newFRUAreaLen);
+
+    // Calculate new checksum
+    std::vector<uint8_t> finalFRUData;
+    std::copy_n(fruData.begin() + fruAreaStart, checksumLoc - fruAreaStart,
+                std::back_inserter(finalFRUData));
+
+    fruData[checksumLoc] = calculateChecksum(finalFRUData);
+    return checksumLoc;
+}
+
+ssize_t getFieldLength(uint8_t fruFieldTypeLenValue)
+{
+    constexpr uint8_t typeLenMask = 0x3F;
+    constexpr uint8_t endOfFields = 0xC1;
+    if (fruFieldTypeLenValue == endOfFields)
+    {
+        return -1;
+    }
+    return fruFieldTypeLenValue & typeLenMask;
+}
+
+bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData)
+{
+    // ipmi spec format version number is currently at 1, verify it
+    if (blockData[0] != fruVersion)
+    {
+        lg2::debug(
+            "FRU spec version {VERSION} not supported. Supported version is {SUPPORTED_VERSION}",
+            "VERSION", lg2::hex, blockData[0], "SUPPORTED_VERSION", lg2::hex,
+            fruVersion);
+        return false;
+    }
+
+    // verify pad is set to 0
+    if (blockData[6] != 0x0)
+    {
+        lg2::debug("Pad value in header is non zero, value is {VALUE}", "VALUE",
+                   lg2::hex, blockData[6]);
+        return false;
+    }
+
+    // verify offsets are 0, or don't point to another offset
+    std::set<uint8_t> foundOffsets;
+    for (int ii = 1; ii < 6; ii++)
+    {
+        if (blockData[ii] == 0)
+        {
+            continue;
+        }
+        auto inserted = foundOffsets.insert(blockData[ii]);
+        if (!inserted.second)
+        {
+            return false;
+        }
+    }
+
+    // validate checksum
+    size_t sum = 0;
+    for (int jj = 0; jj < 7; jj++)
+    {
+        sum += blockData[jj];
+    }
+    sum = (256 - sum) & 0xFF;
+
+    if (sum != blockData[7])
+    {
+        lg2::debug(
+            "Checksum {CHECKSUM} is invalid. calculated checksum is {CALCULATED_CHECKSUM}",
+            "CHECKSUM", lg2::hex, blockData[7], "CALCULATED_CHECKSUM", lg2::hex,
+            sum);
+        return false;
+    }
+    return true;
+}
+
+bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
+                   std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData,
+                   off_t& baseOffset)
+{
+    if (reader.read(baseOffset, 0x8, blockData.data()) < 0)
+    {
+        std::cerr << "failed to read " << errorHelp << " base offset "
+                  << baseOffset << "\n";
+        return false;
+    }
+
+    // check the header checksum
+    if (validateHeader(blockData))
+    {
+        return true;
+    }
+
+    // only continue the search if we just looked at 0x0.
+    if (baseOffset != 0)
+    {
+        return false;
+    }
+
+    // now check for special cases where the IPMI data is at an offset
+
+    // check if blockData starts with tyanHeader
+    const std::vector<uint8_t> tyanHeader = {'$', 'T', 'Y', 'A', 'N', '$'};
+    if (blockData.size() >= tyanHeader.size() &&
+        std::equal(tyanHeader.begin(), tyanHeader.end(), blockData.begin()))
+    {
+        // look for the FRU header at offset 0x6000
+        baseOffset = 0x6000;
+        return findFRUHeader(reader, errorHelp, blockData, baseOffset);
+    }
+
+    lg2::debug("Illegal header {HEADER} base offset {OFFSET}", "HEADER",
+               errorHelp, "OFFSET", baseOffset);
+
+    return false;
+}
+
+std::pair<std::vector<uint8_t>, bool> readFRUContents(
+    FRUReader& reader, const std::string& errorHelp)
+{
+    std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
+    off_t baseOffset = 0x0;
+
+    if (!findFRUHeader(reader, errorHelp, blockData, baseOffset))
+    {
+        return {{}, false};
+    }
+
+    std::vector<uint8_t> device;
+    device.insert(device.end(), blockData.begin(), blockData.begin() + 8);
+
+    bool hasMultiRecords = false;
+    size_t fruLength = fruBlockSize; // At least FRU header is present
+    unsigned int prevOffset = 0;
+    for (fruAreas area = fruAreas::fruAreaInternal;
+         area <= fruAreas::fruAreaMultirecord; ++area)
+    {
+        // Offset value can be 255.
+        unsigned int areaOffset = device[getHeaderAreaFieldOffset(area)];
+        if (areaOffset == 0)
+        {
+            continue;
+        }
+
+        /* Check for offset order, as per Section 17 of FRU specification, FRU
+         * information areas are required to be in order in FRU data layout
+         * which means all offset value should be in increasing order or can be
+         * 0 if that area is not present
+         */
+        if (areaOffset <= prevOffset)
+        {
+            std::cerr << "Fru area offsets are not in required order as per "
+                         "Section 17 of Fru specification\n";
+            return {{}, true};
+        }
+        prevOffset = areaOffset;
+
+        // MultiRecords are different. area is not tracking section, it's
+        // walking the common header.
+        if (area == fruAreas::fruAreaMultirecord)
+        {
+            hasMultiRecords = true;
+            break;
+        }
+
+        areaOffset *= fruBlockSize;
+
+        if (reader.read(baseOffset + areaOffset, 0x2, blockData.data()) < 0)
+        {
+            std::cerr << "failed to read " << errorHelp << " base offset "
+                      << baseOffset << "\n";
+            return {{}, true};
+        }
+
+        // Ignore data type (blockData is already unsigned).
+        size_t length = blockData[1] * fruBlockSize;
+        areaOffset += length;
+        fruLength = (areaOffset > fruLength) ? areaOffset : fruLength;
+    }
+
+    if (hasMultiRecords)
+    {
+        // device[area count] is the index to the last area because the 0th
+        // entry is not an offset in the common header.
+        unsigned int areaOffset =
+            device[getHeaderAreaFieldOffset(fruAreas::fruAreaMultirecord)];
+        areaOffset *= fruBlockSize;
+
+        // the multi-area record header is 5 bytes long.
+        constexpr size_t multiRecordHeaderSize = 5;
+        constexpr uint8_t multiRecordEndOfListMask = 0x80;
+
+        // Sanity hard-limit to 64KB.
+        while (areaOffset < std::numeric_limits<uint16_t>::max())
+        {
+            // In multi-area, the area offset points to the 0th record, each
+            // record has 3 bytes of the header we care about.
+            if (reader.read(baseOffset + areaOffset, 0x3, blockData.data()) < 0)
+            {
+                std::cerr << "failed to read " << errorHelp << " base offset "
+                          << baseOffset << "\n";
+                return {{}, true};
+            }
+
+            // Ok, let's check the record length, which is in bytes (unsigned,
+            // up to 255, so blockData should hold uint8_t not char)
+            size_t recordLength = blockData[2];
+            areaOffset += (recordLength + multiRecordHeaderSize);
+            fruLength = (areaOffset > fruLength) ? areaOffset : fruLength;
+
+            // If this is the end of the list bail.
+            if ((blockData[1] & multiRecordEndOfListMask) != 0)
+            {
+                break;
+            }
+        }
+    }
+
+    // You already copied these first 8 bytes (the ipmi fru header size)
+    fruLength -= std::min(fruBlockSize, fruLength);
+
+    int readOffset = fruBlockSize;
+
+    while (fruLength > 0)
+    {
+        size_t requestLength =
+            std::min(static_cast<size_t>(I2C_SMBUS_BLOCK_MAX), fruLength);
+
+        if (reader.read(baseOffset + readOffset, requestLength,
+                        blockData.data()) < 0)
+        {
+            std::cerr << "failed to read " << errorHelp << " base offset "
+                      << baseOffset << "\n";
+            return {{}, true};
+        }
+
+        device.insert(device.end(), blockData.begin(),
+                      blockData.begin() + requestLength);
+
+        readOffset += requestLength;
+        fruLength -= std::min(requestLength, fruLength);
+    }
+
+    return {device, true};
+}
+
+unsigned int getHeaderAreaFieldOffset(fruAreas area)
+{
+    return static_cast<unsigned int>(area) + 1;
+}
+
+std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address)
+{
+    auto deviceMap = busMap.find(bus);
+    if (deviceMap == busMap.end())
+    {
+        throw std::invalid_argument("Invalid Bus.");
+    }
+    auto device = deviceMap->second->find(address);
+    if (device == deviceMap->second->end())
+    {
+        throw std::invalid_argument("Invalid Address.");
+    }
+    std::vector<uint8_t>& ret = device->second;
+
+    return ret;
+}
+
+// Iterate FruArea Names and find start and size of the fru area that contains
+// the propertyName and the field start location for the property. fruAreaParams
+// struct values fruAreaStart, fruAreaSize, fruAreaEnd, fieldLoc values gets
+// updated/returned if successful.
+
+bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
+                                 const std::string& propertyName,
+                                 struct FruArea& fruAreaParams)
+{
+    const std::vector<std::string>* fruAreaFieldNames = nullptr;
+
+    uint8_t fruAreaOffsetFieldValue = 0;
+    size_t offset = 0;
+    std::string areaName = propertyName.substr(0, propertyName.find('_'));
+    std::string propertyNamePrefix = areaName + "_";
+    auto it = std::find(fruAreaNames.begin(), fruAreaNames.end(), areaName);
+    if (it == fruAreaNames.end())
+    {
+        std::cerr << "Can't parse area name for property " << propertyName
+                  << " \n";
+        return false;
+    }
+    fruAreas fruAreaToUpdate = static_cast<fruAreas>(it - fruAreaNames.begin());
+    fruAreaOffsetFieldValue =
+        fruData[getHeaderAreaFieldOffset(fruAreaToUpdate)];
+    switch (fruAreaToUpdate)
+    {
+        case fruAreas::fruAreaChassis:
+            offset = 3; // chassis part number offset. Skip fixed first 3 bytes
+            fruAreaFieldNames = &chassisFruAreas;
+            break;
+        case fruAreas::fruAreaBoard:
+            offset = 6; // board manufacturer offset. Skip fixed first 6 bytes
+            fruAreaFieldNames = &boardFruAreas;
+            break;
+        case fruAreas::fruAreaProduct:
+            // Manufacturer name offset. Skip fixed first 3 product fru bytes
+            // i.e. version, area length and language code
+            offset = 3;
+            fruAreaFieldNames = &productFruAreas;
+            break;
+        default:
+            std::cerr << "Invalid PropertyName " << propertyName << " \n";
+            return false;
+    }
+    if (fruAreaOffsetFieldValue == 0)
+    {
+        std::cerr << "FRU Area for " << propertyName << " not present \n";
+        return false;
+    }
+
+    fruAreaParams.start = fruAreaOffsetFieldValue * fruBlockSize;
+    fruAreaParams.size = fruData[fruAreaParams.start + 1] * fruBlockSize;
+    fruAreaParams.end = fruAreaParams.start + fruAreaParams.size;
+    size_t fruDataIter = fruAreaParams.start + offset;
+    size_t skipToFRUUpdateField = 0;
+    ssize_t fieldLength = 0;
+
+    bool found = false;
+    for (const auto& field : *fruAreaFieldNames)
+    {
+        skipToFRUUpdateField++;
+        if (propertyName == propertyNamePrefix + field)
+        {
+            found = true;
+            break;
+        }
+    }
+    if (!found)
+    {
+        std::size_t pos = propertyName.find(fruCustomFieldName);
+        if (pos == std::string::npos)
+        {
+            std::cerr << "PropertyName doesn't exist in FRU Area Vectors: "
+                      << propertyName << "\n";
+            return false;
+        }
+        std::string fieldNumStr =
+            propertyName.substr(pos + fruCustomFieldName.length());
+        size_t fieldNum = std::stoi(fieldNumStr);
+        if (fieldNum == 0)
+        {
+            std::cerr << "PropertyName not recognized: " << propertyName
+                      << "\n";
+            return false;
+        }
+        skipToFRUUpdateField += fieldNum;
+    }
+
+    for (size_t i = 1; i < skipToFRUUpdateField; i++)
+    {
+        if (fruDataIter < fruData.size())
+        {
+            fieldLength = getFieldLength(fruData[fruDataIter]);
+
+            if (fieldLength < 0)
+            {
+                break;
+            }
+            fruDataIter += 1 + fieldLength;
+        }
+    }
+    fruAreaParams.updateFieldLoc = fruDataIter;
+
+    return true;
+}
+
+// Copy the FRU Area fields and properties into restFRUAreaFieldsData vector.
+// Return true for success and false for failure.
+
+bool copyRestFRUArea(std::vector<uint8_t>& fruData,
+                     const std::string& propertyName,
+                     struct FruArea& fruAreaParams,
+                     std::vector<uint8_t>& restFRUAreaFieldsData)
+{
+    size_t fieldLoc = fruAreaParams.updateFieldLoc;
+    size_t start = fruAreaParams.start;
+    size_t fruAreaSize = fruAreaParams.size;
+
+    // Push post update fru field bytes to a vector
+    ssize_t fieldLength = getFieldLength(fruData[fieldLoc]);
+    if (fieldLength < 0)
+    {
+        std::cerr << "Property " << propertyName << " not present \n";
+        return false;
+    }
+
+    size_t fruDataIter = 0;
+    fruDataIter = fieldLoc;
+    fruDataIter += 1 + fieldLength;
+    size_t restFRUFieldsLoc = fruDataIter;
+    size_t endOfFieldsLoc = 0;
+
+    if (fruDataIter < fruData.size())
+    {
+        while ((fieldLength = getFieldLength(fruData[fruDataIter])) >= 0)
+        {
+            if (fruDataIter >= (start + fruAreaSize))
+            {
+                fruDataIter = start + fruAreaSize;
+                break;
+            }
+            fruDataIter += 1 + fieldLength;
+        }
+        endOfFieldsLoc = fruDataIter;
+    }
+
+    std::copy_n(fruData.begin() + restFRUFieldsLoc,
+                endOfFieldsLoc - restFRUFieldsLoc + 1,
+                std::back_inserter(restFRUAreaFieldsData));
+
+    fruAreaParams.restFieldsLoc = restFRUFieldsLoc;
+    fruAreaParams.restFieldsEnd = endOfFieldsLoc;
+
+    return true;
+}
+
+// Get all device dbus path and match path with product name using
+// regular expression and find the device index for all devices.
+
+std::optional<int> findIndexForFRU(
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    std::string& productName)
+{
+    int highest = -1;
+    bool found = false;
+
+    for (const auto& busIface : dbusInterfaceMap)
+    {
+        std::string path = busIface.second->get_object_path();
+        if (std::regex_match(path, std::regex(productName + "(_\\d+|)$")))
+        {
+            // Check if the match named has extra information.
+            found = true;
+            std::smatch baseMatch;
+
+            bool match = std::regex_match(path, baseMatch,
+                                          std::regex(productName + "_(\\d+)$"));
+            if (match)
+            {
+                if (baseMatch.size() == 2)
+                {
+                    std::ssub_match baseSubMatch = baseMatch[1];
+                    std::string base = baseSubMatch.str();
+
+                    int value = std::stoi(base);
+                    highest = (value > highest) ? value : highest;
+                }
+            }
+        }
+    } // end searching objects
+
+    if (!found)
+    {
+        return std::nullopt;
+    }
+    return highest;
+}
+
+// This function does format fru data as per IPMI format and find the
+// productName in the formatted fru data, get that productName and return
+// productName if found or return NULL.
+
+std::optional<std::string> getProductName(
+    std::vector<uint8_t>& device,
+    boost::container::flat_map<std::string, std::string>& formattedFRU,
+    uint32_t bus, uint32_t address, size_t& unknownBusObjectCount)
+{
+    std::string productName;
+
+    resCodes res = formatIPMIFRU(device, formattedFRU);
+    if (res == resCodes::resErr)
+    {
+        std::cerr << "failed to parse FRU for device at bus " << bus
+                  << " address " << address << "\n";
+        return std::nullopt;
+    }
+    if (res == resCodes::resWarn)
+    {
+        std::cerr << "Warnings while parsing FRU for device at bus " << bus
+                  << " address " << address << "\n";
+    }
+
+    auto productNameFind = formattedFRU.find("BOARD_PRODUCT_NAME");
+    // Not found under Board section or an empty string.
+    if (productNameFind == formattedFRU.end() ||
+        productNameFind->second.empty())
+    {
+        productNameFind = formattedFRU.find("PRODUCT_PRODUCT_NAME");
+    }
+    // Found under Product section and not an empty string.
+    if (productNameFind != formattedFRU.end() &&
+        !productNameFind->second.empty())
+    {
+        productName = productNameFind->second;
+        std::regex illegalObject("[^A-Za-z0-9_]");
+        productName = std::regex_replace(productName, illegalObject, "_");
+    }
+    else
+    {
+        productName = "UNKNOWN" + std::to_string(unknownBusObjectCount);
+        unknownBusObjectCount++;
+    }
+    return productName;
+}
+
+bool getFruData(std::vector<uint8_t>& fruData, uint32_t bus, uint32_t address)
+{
+    try
+    {
+        fruData = getFRUInfo(static_cast<uint16_t>(bus),
+                             static_cast<uint8_t>(address));
+    }
+    catch (const std::invalid_argument& e)
+    {
+        std::cerr << "Failure getting FRU Info" << e.what() << "\n";
+        return false;
+    }
+
+    return !fruData.empty();
+}
diff --git a/src/fru_device/fru_utils.hpp b/src/fru_device/fru_utils.hpp
new file mode 100644
index 0000000..b427c25
--- /dev/null
+++ b/src/fru_device/fru_utils.hpp
@@ -0,0 +1,227 @@
+/*
+// 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 fru_utils.hpp
+
+#pragma once
+#include "fru_reader.hpp"
+
+#include <boost/container/flat_map.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <cstdint>
+#include <cstdio>
+#include <functional>
+#include <regex>
+#include <string>
+#include <utility>
+#include <vector>
+extern "C"
+{
+// Include for I2C_SMBUS_BLOCK_MAX
+#include <linux/i2c.h>
+}
+
+constexpr size_t fruBlockSize = 8;
+
+using DeviceMap = boost::container::flat_map<int, std::vector<uint8_t>>;
+using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
+
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+inline BusMap busMap;
+
+enum class DecodeState
+{
+    ok,
+    end,
+    err,
+};
+
+enum class resCodes
+{
+    resOK,
+    resWarn,
+    resErr
+};
+
+enum class fruAreas
+{
+    fruAreaInternal = 0,
+    fruAreaChassis,
+    fruAreaBoard,
+    fruAreaProduct,
+    fruAreaMultirecord
+};
+
+struct FruArea
+{
+    size_t start;          // Fru Area Start offset
+    size_t size;           // Fru Area Size
+    size_t end;            // Fru Area end offset
+    size_t updateFieldLoc; // Fru Area update Field Location
+    size_t restFieldsLoc;  // Starting location of restFRUArea data
+    size_t restFieldsEnd;  // Ending location of restFRUArea data
+};
+
+const std::vector<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
+                                               "PRODUCT", "MULTIRECORD"};
+const std::regex nonAsciiRegex("[^\x01-\x7f]");
+
+const std::vector<std::string> chassisFruAreas = {"PART_NUMBER",
+                                                  "SERIAL_NUMBER"};
+
+const std::vector<std::string> boardFruAreas = {
+    "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
+    "FRU_VERSION_ID"};
+
+const std::vector<std::string> productFruAreas = {
+    "MANUFACTURER",  "PRODUCT_NAME", "PART_NUMBER",   "VERSION",
+    "SERIAL_NUMBER", "ASSET_TAG",    "FRU_VERSION_ID"};
+
+const std::string fruCustomFieldName = "INFO_AM";
+
+inline fruAreas operator++(fruAreas& x)
+{
+    return x = static_cast<fruAreas>(
+               std::underlying_type<fruAreas>::type(x) + 1);
+}
+
+inline const std::string& getFruAreaName(fruAreas area)
+{
+    return fruAreaNames[static_cast<unsigned int>(area)];
+}
+
+std::tm intelEpoch();
+
+char sixBitToChar(uint8_t val);
+
+/* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */
+constexpr std::array<char, 6> bcdHighChars = {
+    ' ', '-', '.', 'X', 'X', 'X',
+};
+
+char bcdPlusToChar(uint8_t val);
+
+bool verifyOffset(std::span<const uint8_t> fruBytes, fruAreas currentArea,
+                  uint8_t len);
+
+std::pair<DecodeState, std::string> decodeFRUData(
+    std::span<const uint8_t>::const_iterator& iter,
+    std::span<const uint8_t>::const_iterator& end, bool isLangEng);
+
+bool checkLangEng(uint8_t lang);
+
+resCodes formatIPMIFRU(
+    std::span<const uint8_t> fruBytes,
+    boost::container::flat_map<std::string, std::string>& result);
+
+std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address);
+
+uint8_t calculateChecksum(std::span<const uint8_t>::const_iterator iter,
+                          std::span<const uint8_t>::const_iterator end);
+
+uint8_t calculateChecksum(std::span<const uint8_t> fruAreaData);
+
+unsigned int updateFRUAreaLenAndChecksum(
+    std::vector<uint8_t>& fruData, size_t fruAreaStart,
+    size_t fruAreaEndOfFieldsOffset, size_t fruAreaEndOffset);
+
+ssize_t getFieldLength(uint8_t fruFieldTypeLenValue);
+
+/// \brief Find a FRU header.
+/// \param reader the FRUReader to read via
+/// \param errorHelp and a helper string for failures
+/// \param blockData buffer to return the last read block
+/// \param baseOffset the offset to start the search at;
+///        set to 0 to perform search;
+///        returns the offset at which a header was found
+/// \return whether a header was found
+bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
+                   std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData,
+                   off_t& baseOffset);
+
+/// \brief Read and validate FRU contents.
+/// \param reader the FRUReader to read via
+/// \param errorHelp and a helper string for failures
+/// \return the FRU contents from the file and bool indicating if the FRU Header
+/// was found
+std::pair<std::vector<uint8_t>, bool> readFRUContents(
+    FRUReader& reader, const std::string& errorHelp);
+
+/// \brief Validate an IPMI FRU common header
+/// \param blockData the bytes comprising the common header
+/// \return true if valid
+bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData);
+
+/// \brief Get offset for a common header area
+/// \param area - the area
+/// \return the field offset
+unsigned int getHeaderAreaFieldOffset(fruAreas area);
+
+/// \brief Iterate fruArea Names and find offset/location and fields and size of
+/// properties
+/// \param fruData - vector to store fru data
+/// \param propertyName - fru property Name
+/// \param fruAreaParams - struct to have fru Area parameters like length,
+/// size.
+/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
+/// Start, Size, End are updated with fruArea and field info.
+bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
+                                 const std::string& propertyName,
+                                 struct FruArea& fruAreaParams);
+
+/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
+/// restFRUAreaField is the rest of the fields in FRU area after the field that
+/// is being updated.
+/// \param fruData - vector to store fru data
+/// \param propertyName - fru property Name
+/// \param fruAreaParams - struct to have fru Area parameters like length
+/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
+/// properties.
+/// \return true on success false on failure. restFieldLoc and restFieldEnd
+/// are updated.
+
+bool copyRestFRUArea(std::vector<uint8_t>& fruData,
+                     const std::string& propertyName,
+                     struct FruArea& fruAreaParams,
+                     std::vector<uint8_t>& restFRUAreaFieldsData);
+
+/// \brief Get all device dbus path and match path with product name using
+/// regular expression and find the device index for all devices.
+/// \param dbusInterfaceMap - Map to store fru device dbus path and interface
+/// \param productName - fru device product name.
+/// \return optional<int> highest index for fru device on success, return
+/// nullopt on failure.
+std::optional<int> findIndexForFRU(
+    boost::container::flat_map<
+        std::pair<size_t, size_t>,
+        std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
+    std::string& productName);
+
+/// \brief It does format fru data and find productName in the formatted
+/// fru data and return productName.
+/// \param device - vector that contains device list
+/// \param formattedFRU - map that contains formatted FRU data
+/// \param bus - bus number of the device
+/// \param address - address of the device
+/// \param unknownBusObjectCount - Unknown Bus object counter variable
+/// \return optional string. it returns productName or NULL
+
+std::optional<std::string> getProductName(
+    std::vector<uint8_t>& device,
+    boost::container::flat_map<std::string, std::string>& formattedFRU,
+    uint32_t bus, uint32_t address, size_t& unknownBusObjectCount);
+
+bool getFruData(std::vector<uint8_t>& fruData, uint32_t bus, uint32_t address);
diff --git a/src/fru_device/meson.build b/src/fru_device/meson.build
new file mode 100644
index 0000000..f427f93
--- /dev/null
+++ b/src/fru_device/meson.build
@@ -0,0 +1,28 @@
+cpp_args_fd = cpp_args
+if get_option('fru-device-resizefru')
+    cpp_args_fd = cpp_args_fd + ['-DENABLE_FRU_AREA_RESIZE']
+endif
+detect_mode = get_option('fru-device-16bitdetectmode')
+cpp_args_fd += ['-DFRU_DEVICE_16BITDETECTMODE="' + detect_mode + '"']
+executable(
+    'fru-device',
+    '../expression.cpp',
+    'fru_device.cpp',
+    '../utils.cpp',
+    'fru_utils.cpp',
+    'fru_reader.cpp',
+    cpp_args: cpp_args_fd,
+    dependencies: [
+        boost,
+        i2c,
+        nlohmann_json_dep,
+        phosphor_logging_dep,
+        sdbusplus,
+        threads,
+        valijson,
+    ],
+    install: true,
+    install_dir: installdir,
+)
+
+
