/*
// 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

// NOLINTBEGIN
#include "tlbmc/utils/fru_utils.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <limits>
#include <numeric>
#include <optional>
#include <regex>  // NOLINT
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/log/log.h"
#include "tlbmc/utils/fru_reader.h"

namespace milotic_tlbmc {

static constexpr bool debug = false;
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
};

std::string resCodesToString(resCodes resCode) {
  switch (resCode) {
    case resCodes::resOK:
      return "OK";
    case resCodes::resWarn:
      return "WARNING";
    case resCodes::resErr:
      return "ERROR";
    default:
      return "INVALID";
  }
}

/* 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::vector<uint8_t>::const_iterator& iter,
    const std::vector<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) {
    LOG(WARNING) << "Truncated FRU data";
    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) {
    LOG(WARNING) << "FRU data field extends past end of FRU area data";
    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) {
        LOG(WARNING) << "Error: Non english string is not supported ";
        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) {
    LOG(WARNING) << "Warning: languages other than English is not "
                    "supported";
    // 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(const std::vector<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) {
    LOG(WARNING) << "Error: trying to parse empty FRU";
    return false;
  }

  // Check range of passed currentArea value
  if (currentArea > fruAreas::fruAreaMultirecord) {
    LOG(WARNING) << "Error: Fru area is out of range";
    return false;
  }

  unsigned int currentAreaIndex = getHeaderAreaFieldOffset(currentArea);
  if (currentAreaIndex > fruBytesSize) {
    LOG(WARNING) << "Error: Fru area index is out of range";
    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) {
      LOG(WARNING) << "Error: Fru area index is out of range";
      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)) {
      LOG(WARNING) << getFruAreaName(currentArea)
                   << " offset is overlapping with " << getFruAreaName(area)
                   << " offset";
      return false;
    }
  }
  return true;
}

void parseMultirecordUUID(
    const std::vector<uint8_t>& device,
    absl::flat_hash_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};
  uint32_t areaOffset =
      device.at(getHeaderAreaFieldOffset(fruAreas::fruAreaMultirecord));

  if (areaOffset == 0) {
    return;
  }

  areaOffset *= fruBlockSize;
  std::vector<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;
  }
}

void parseInternalUseArea(
    const std::vector<uint8_t>& fruBytes,
    absl::flat_hash_map<std::string, std::string>& result) {
  fruAreas area = fruAreas::fruAreaInternal;
  size_t offset = *(fruBytes.begin() + getHeaderAreaFieldOffset(area));
  if (offset == 0) {
    return;
  }
  offset *= fruBlockSize;
  std::vector<uint8_t>::const_iterator fruBytesIter = fruBytes.begin() + offset;
  if (fruBytesIter + fruBlockSize >= fruBytes.end()) {
    LOG(WARNING) << "Not enough data to parse ";
    return;
  }
  if (!verifyOffset(fruBytes, area, *fruBytesIter)) {
    LOG(WARNING) << "Internal area offset is overlapping with other area ";
    return;
  }
  // check for format version 1
  if (*fruBytesIter != 0x01) {
    LOG(WARNING) << "Unexpected version " << *fruBytesIter;
    return;
  }
  ++fruBytesIter;
  // check for MAC payload type
  if (*fruBytesIter != 0x01) {
    LOG(WARNING) << "SKIPPING non MAC information: " << *fruBytesIter;
    return;
  }
  ++fruBytesIter;

  size_t fruAreaSize = *fruBytesIter;
  std::vector<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);
    ss << "\tComputed checksum: 0x" << std::setw(2)
       << static_cast<int>(fruComputedChecksum);
    ss << "\tThe read checksum: 0x" << std::setw(2)
       << static_cast<int>(*fruBytesIterEndArea);
    LOG(WARNING) << ss.str();
    return;
  }

  if (fruBytesIter + 6 > fruBytes.end()) {
    LOG(WARNING) << "Not enough data to parse Internal Use Area MAC";
    return;
  }
  std::stringstream ss;
  ss << std::hex << std::setfill('0');
  for (int i = 0; i < 6; ++i) {
    if (i > 0) ss << ":";
    ss << std::setw(2) << static_cast<int>(*(fruBytesIter + i));
  }
  result["INTERNAL_MAC_ADDRESS"] = ss.str();
}

resCodes formatIPMIFRU(const std::vector<uint8_t>& fruBytes,
                       absl::flat_hash_map<std::string, std::string>& result) {
  resCodes ret = resCodes::resOK;
  if (fruBytes.size() <= fruBlockSize) {
    LOG(WARNING) << "Error: trying to parse empty FRU ";
    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 Use Area or 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::vector<uint8_t>::const_iterator fruBytesIter =
        fruBytes.begin() + offset;
    if (fruBytesIter + fruBlockSize >= fruBytes.end()) {
      LOG(WARNING) << "Not enough data to parse ";
      return resCodes::resErr;
    }
    // check for format version 1
    if (*fruBytesIter != 0x01) {
      LOG(WARNING) << "Unexpected version " << *fruBytesIter;
      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::vector<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);
      ss << "\tComputed checksum: 0x" << std::setw(2)
         << static_cast<int>(fruComputedChecksum);
      ss << "\tThe read checksum: 0x" << std::setw(2)
         << static_cast<int>(*fruBytesIterEndArea);
      LOG(WARNING) << 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) {
          LOG(WARNING) << "invalid time string encountered";
          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: {
        LOG(WARNING) << "Internal error: unexpected FRU area index: "
                     << static_cast<int>(area) << " ";
        return resCodes::resErr;
      }
    }
    size_t fieldIndex = 0;
    DecodeState state = DecodeState::ok;
    do {
      auto res = decodeFRUData(fruBytesIter, fruBytesIterEndArea, isLangEng);
      state = res.first;
      std::string value = res.second;
      std::string name;
      if (fieldIndex < fruAreaFieldNames->size()) {
        name = std::string(getFruAreaName(area)) + "_" +
               fruAreaFieldNames->at(fieldIndex);
      } else {
        name = std::string(getFruAreaName(area)) + "_" + fruCustomFieldName +
               std::to_string(fieldIndex - fruAreaFieldNames->size() + 1);
      }

      if (state == DecodeState::ok) {
        // Strip non null characters from the end
        value.erase(std::find_if(value.rbegin(), value.rend(),
                                 [](char ch) { return ch != 0; })
                        .base(),
                    value.end());

        result[name] = std::move(value);
        ++fieldIndex;
      } else if (state == DecodeState::err) {
        LOG(WARNING) << "Error while parsing " << name;
        ret = resCodes::resWarn;
        // Cancel decoding if failed to parse any of mandatory
        // fields
        if (fieldIndex < fruAreaFieldNames->size()) {
          LOG(WARNING) << "Failed to parse mandatory field ";
          return resCodes::resErr;
        }
      } else {
        if (fieldIndex < fruAreaFieldNames->size()) {
          LOG(WARNING) << "Mandatory fields absent in FRU area "
                       << getFruAreaName(area) << " after " << name;
          ret = resCodes::resWarn;
        }
      }
    } while (state == DecodeState::ok);
    for (; fruBytesIter < fruBytesIterEndArea; fruBytesIter++) {
      uint8_t c = *fruBytesIter;
      if (c != 0U) {
        LOG(WARNING) << "Non-zero byte after EndOfFields in FRU area "
                     << getFruAreaName(area);
        ret = resCodes::resWarn;
        break;
      }
    }
  }

  /* Parsing the Internal Use Area */
  parseInternalUseArea(fruBytes, result);
  /* Parsing the Multirecord UUID */
  parseMultirecordUUID(fruBytes, result);

  return ret;
}

// Calculate new checksum for fru info area
uint8_t calculateChecksum(std::vector<uint8_t>::const_iterator iter,
                          std::vector<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::vector<uint8_t>& fruAreaData) {
  return calculateChecksum(fruAreaData.begin(), fruAreaData.end());
}

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) {
    if (debug) {
      LOG(WARNING) << "FRU spec version " << (int)(blockData[0])
                   << " not supported. Supported version is "
                   << (int)(fruVersion);
    }
    return false;
  }

  // verify pad is set to 0
  if (blockData[6] != 0x0) {
    if (debug) {
      LOG(WARNING) << "PAD value in header is non zero, value is "
                   << (int)(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]) {
    if (debug) {
      LOG(WARNING) << "Checksum " << (int)(blockData[7])
                   << " is invalid. calculated checksum is " << (int)(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) {
    LOG(WARNING) << "failed to read " << errorHelp << " base offset "
                 << baseOffset;
    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);
  }

  if (debug) {
    LOG(WARNING) << "Illegal header " << errorHelp << " base 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)) {
    // Empty eeprom fails here as well
    LOG(WARNING) << "failed to find FRU header for " << errorHelp;
    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) {
      LOG(WARNING) << "Fru area offsets are not in required order as per "
                      "Section 17 of Fru specification";
      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) {
      LOG(WARNING) << "failed to read " << errorHelp << " base offset "
                   << baseOffset;
      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) {
        LOG(WARNING) << "failed to read " << errorHelp << " base offset "
                     << baseOffset;
        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) {
      LOG(WARNING) << "failed to read " << errorHelp << " base offset "
                   << baseOffset;
      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::string getProductNameFromFormattedFru(
    const absl::flat_hash_map<std::string, std::string>& formattedFRU,
    size_t& unknownBusObjectCount) {
  std::string productName;

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

// This function formats fru data as per IPMI format and finds 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,
    absl::flat_hash_map<std::string, std::string>& formattedFRU, uint32_t bus,
    uint32_t address, size_t& unknownBusObjectCount) {
  resCodes res = formatIPMIFRU(device, formattedFRU);
  if (res == resCodes::resErr) {
    LOG(WARNING) << "failed to parse FRU for device at bus " << bus
                 << " address " << address;
    return std::nullopt;
  }
  if (res == resCodes::resWarn) {
    LOG(WARNING) << "Warnings while parsing FRU for device at bus " << bus
                 << " address " << address;
  }

  return getProductNameFromFormattedFru(formattedFRU, unknownBusObjectCount);
}

}  // namespace milotic_tlbmc
// NOLINTEND
