| /* |
| // 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(const std::vector<uint8_t>& fruBytes, fruAreas currentArea, |
| uint8_t len); |
| |
| std::pair<DecodeState, std::string> decodeFRUData( |
| std::vector<uint8_t>::const_iterator& iter, |
| const std::vector<uint8_t>::const_iterator& end, bool isLangEng); |
| |
| bool checkLangEng(uint8_t lang); |
| |
| resCodes |
| formatIPMIFRU(const std::vector<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::vector<uint8_t>::const_iterator iter, |
| std::vector<uint8_t>::const_iterator end); |
| |
| uint8_t calculateChecksum(std::vector<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); |