// SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation #pragma once #include "fru_reader.hpp" #include #include #include #include #include #include #include #include #include extern "C" { // Include for I2C_SMBUS_BLOCK_MAX #include } constexpr size_t fruBlockSize = 8; using DeviceMap = boost::container::flat_map>; using BusMap = boost::container::flat_map>; // 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 fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD", "PRODUCT", "MULTIRECORD"}; const std::regex nonAsciiRegex("[^\x01-\x7f]"); const std::vector chassisFruAreas = {"PART_NUMBER", "SERIAL_NUMBER"}; const std::vector boardFruAreas = { "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER", "FRU_VERSION_ID"}; const std::vector 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( std::underlying_type::type(x) + 1); } inline const std::string& getFruAreaName(fruAreas area) { return fruAreaNames[static_cast(area)]; } std::tm intelEpoch(); char sixBitToChar(uint8_t val); /* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */ constexpr std::array bcdHighChars = { ' ', '-', '.', 'X', 'X', 'X', }; char bcdPlusToChar(uint8_t val); bool verifyOffset(std::span fruBytes, fruAreas currentArea, uint8_t len); std::pair decodeFRUData( std::span::const_iterator& iter, std::span::const_iterator& end, bool isLangEng); bool checkLangEng(uint8_t lang); resCodes formatIPMIFRU( std::span fruBytes, boost::container::flat_map& result); std::vector& getFRUInfo(const uint16_t& bus, const uint8_t& address); uint8_t calculateChecksum(std::span::const_iterator iter, std::span::const_iterator end); uint8_t calculateChecksum(std::span fruAreaData); unsigned int updateFRUAreaLenAndChecksum( std::vector& 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& 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, 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& 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& 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& fruData, const std::string& propertyName, struct FruArea& fruAreaParams, std::vector& 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 highest index for fru device on success, return /// nullopt on failure. std::optional findIndexForFRU( boost::container::flat_map< std::pair, std::shared_ptr>& 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 getProductName( std::vector& device, boost::container::flat_map& formattedFRU, uint32_t bus, uint32_t address, size_t& unknownBusObjectCount); bool getFruData(std::vector& fruData, uint32_t bus, uint32_t address); bool isFieldEditable(std::string_view fieldName);