| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | // Copyright (c) 2018 Intel Corporation | 
|  | 3 | // | 
|  | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | // you may not use this file except in compliance with the License. | 
|  | 6 | // You may obtain a copy of the License at | 
|  | 7 | // | 
|  | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | // | 
|  | 10 | // Unless required by applicable law or agreed to in writing, software | 
|  | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | // See the License for the specific language governing permissions and | 
|  | 14 | // limitations under the License. | 
|  | 15 | */ | 
|  | 16 | /// \file FruUtils.hpp | 
|  | 17 |  | 
|  | 18 | #pragma once | 
| Kumar Thangavel | c8dc4af | 2021-01-12 10:36:38 +0530 | [diff] [blame^] | 19 | #include <boost/container/flat_map.hpp> | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 20 |  | 
|  | 21 | #include <cstdint> | 
|  | 22 | #include <functional> | 
| Kumar Thangavel | c8dc4af | 2021-01-12 10:36:38 +0530 | [diff] [blame^] | 23 | #include <regex> | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 24 | #include <string> | 
| Kumar Thangavel | c8dc4af | 2021-01-12 10:36:38 +0530 | [diff] [blame^] | 25 | #include <utility> | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 26 | #include <vector> | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 27 | extern "C" | 
|  | 28 | { | 
|  | 29 | // Include for I2C_SMBUS_BLOCK_MAX | 
|  | 30 | #include <linux/i2c.h> | 
|  | 31 | } | 
|  | 32 |  | 
| Kumar Thangavel | c8dc4af | 2021-01-12 10:36:38 +0530 | [diff] [blame^] | 33 | constexpr size_t fruBlockSize = 8; | 
|  | 34 |  | 
|  | 35 | enum class DecodeState | 
|  | 36 | { | 
|  | 37 | ok, | 
|  | 38 | end, | 
|  | 39 | err, | 
|  | 40 | }; | 
|  | 41 |  | 
|  | 42 | enum class resCodes | 
|  | 43 | { | 
|  | 44 | resOK, | 
|  | 45 | resWarn, | 
|  | 46 | resErr | 
|  | 47 | }; | 
|  | 48 |  | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 49 | enum class fruAreas | 
|  | 50 | { | 
|  | 51 | fruAreaInternal = 0, | 
|  | 52 | fruAreaChassis, | 
|  | 53 | fruAreaBoard, | 
|  | 54 | fruAreaProduct, | 
|  | 55 | fruAreaMultirecord | 
|  | 56 | }; | 
| Kumar Thangavel | c8dc4af | 2021-01-12 10:36:38 +0530 | [diff] [blame^] | 57 |  | 
|  | 58 | const std::vector<std::string> FRU_AREA_NAMES = {"INTERNAL", "CHASSIS", "BOARD", | 
|  | 59 | "PRODUCT", "MULTIRECORD"}; | 
|  | 60 | const std::regex NON_ASCII_REGEX("[^\x01-\x7f]"); | 
|  | 61 |  | 
|  | 62 | const std::vector<std::string> CHASSIS_FRU_AREAS = {"PART_NUMBER", | 
|  | 63 | "SERIAL_NUMBER"}; | 
|  | 64 |  | 
|  | 65 | const std::vector<std::string> BOARD_FRU_AREAS = { | 
|  | 66 | "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER", | 
|  | 67 | "FRU_VERSION_ID"}; | 
|  | 68 |  | 
|  | 69 | const std::vector<std::string> PRODUCT_FRU_AREAS = { | 
|  | 70 | "MANUFACTURER",  "PRODUCT_NAME", "PART_NUMBER",   "VERSION", | 
|  | 71 | "SERIAL_NUMBER", "ASSET_TAG",    "FRU_VERSION_ID"}; | 
|  | 72 |  | 
|  | 73 | const std::string FRU_CUSTOM_FIELD_NAME = "INFO_AM"; | 
|  | 74 |  | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 75 | inline fruAreas operator++(fruAreas& x) | 
|  | 76 | { | 
|  | 77 | return x = static_cast<fruAreas>(std::underlying_type<fruAreas>::type(x) + | 
|  | 78 | 1); | 
|  | 79 | } | 
|  | 80 |  | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 81 | using ReadBlockFunc = | 
|  | 82 | std::function<int64_t(int flag, int file, uint16_t address, uint16_t offset, | 
|  | 83 | uint8_t length, uint8_t* outBuf)>; | 
|  | 84 |  | 
| Kumar Thangavel | c8dc4af | 2021-01-12 10:36:38 +0530 | [diff] [blame^] | 85 | inline const std::string& getFruAreaName(fruAreas area) | 
|  | 86 | { | 
|  | 87 | return FRU_AREA_NAMES[static_cast<unsigned int>(area)]; | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | const std::tm intelEpoch(void); | 
|  | 91 |  | 
|  | 92 | char sixBitToChar(uint8_t val); | 
|  | 93 |  | 
|  | 94 | /* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */ | 
|  | 95 | const char bcdHighChars[] = { | 
|  | 96 | ' ', '-', '.', 'X', 'X', 'X', | 
|  | 97 | }; | 
|  | 98 |  | 
|  | 99 | char bcdPlusToChar(uint8_t val); | 
|  | 100 |  | 
|  | 101 | bool verifyOffset(const std::vector<uint8_t>& fruBytes, fruAreas currentArea, | 
|  | 102 | uint8_t len); | 
|  | 103 |  | 
|  | 104 | std::pair<DecodeState, std::string> | 
|  | 105 | decodeFRUData(std::vector<uint8_t>::const_iterator& iter, | 
|  | 106 | const std::vector<uint8_t>::const_iterator& end, | 
|  | 107 | bool isLangEng); | 
|  | 108 |  | 
|  | 109 | bool checkLangEng(uint8_t lang); | 
|  | 110 |  | 
|  | 111 | resCodes | 
|  | 112 | formatFRU(const std::vector<uint8_t>& fruBytes, | 
|  | 113 | boost::container::flat_map<std::string, std::string>& result); | 
|  | 114 |  | 
|  | 115 | std::vector<uint8_t>& getFRUInfo(const uint8_t& bus, const uint8_t& address); | 
|  | 116 |  | 
|  | 117 | uint8_t calculateChecksum(std::vector<uint8_t>::const_iterator iter, | 
|  | 118 | std::vector<uint8_t>::const_iterator end); | 
|  | 119 |  | 
|  | 120 | uint8_t calculateChecksum(std::vector<uint8_t>& fruAreaData); | 
|  | 121 |  | 
|  | 122 | unsigned int updateFRUAreaLenAndChecksum(std::vector<uint8_t>& fruData, | 
|  | 123 | size_t fruAreaStart, | 
|  | 124 | size_t fruAreaEndOfFieldsOffset, | 
|  | 125 | size_t fruAreaEndOffset); | 
|  | 126 |  | 
|  | 127 | ssize_t getFieldLength(uint8_t fruFieldTypeLenValue); | 
|  | 128 |  | 
| Patrick Venture | ab29641 | 2020-12-30 13:39:37 -0800 | [diff] [blame] | 129 | /// \brief Read and validate FRU contents. | 
|  | 130 | /// \param flag the flag required for raw i2c | 
|  | 131 | /// \param file the open file handle | 
|  | 132 | /// \param address the i2c device address | 
|  | 133 | /// \param readBlock a read method | 
|  | 134 | /// \param errorHelp and a helper string for failures | 
|  | 135 | /// \return the FRU contents from the file | 
|  | 136 | std::vector<uint8_t> readFRUContents(int flag, int file, uint16_t address, | 
|  | 137 | ReadBlockFunc readBlock, | 
|  | 138 | const std::string& errorHelp); | 
|  | 139 |  | 
|  | 140 | /// \brief Validate an IPMI FRU common header | 
|  | 141 | /// \param blockData the bytes comprising the common header | 
|  | 142 | /// \return true if valid | 
|  | 143 | bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData); | 
|  | 144 |  | 
|  | 145 | /// \brief Get offset for a common header area | 
|  | 146 | /// \param area - the area | 
|  | 147 | /// \return the field offset | 
|  | 148 | unsigned int getHeaderAreaFieldOffset(fruAreas area); |