blob: 8a117a76970b5b5fc79ec79c7a3fd6142bf2aee8 [file] [log] [blame]
Patrick Ventureab296412020-12-30 13:39:37 -08001/*
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*/
Brad Bishope45d8c72022-05-25 15:12:53 -040016/// \file fru_utils.hpp
Patrick Ventureab296412020-12-30 13:39:37 -080017
18#pragma once
Zev Weiss309c0b12022-02-25 01:44:12 +000019#include "fru_reader.hpp"
Ed Tanous3013fb42022-07-09 08:27:06 -070020
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053021#include <boost/container/flat_map.hpp>
Kumar Thangaveld79d0252022-08-24 14:26:01 +053022#include <sdbusplus/asio/object_server.hpp>
Patrick Ventureab296412020-12-30 13:39:37 -080023
24#include <cstdint>
Patrick Williamsb9a1f962024-07-13 16:34:49 -050025#include <cstdio>
Patrick Ventureab296412020-12-30 13:39:37 -080026#include <functional>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053027#include <regex>
Patrick Ventureab296412020-12-30 13:39:37 -080028#include <string>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053029#include <utility>
Patrick Ventureab296412020-12-30 13:39:37 -080030#include <vector>
Patrick Ventureab296412020-12-30 13:39:37 -080031extern "C"
32{
33// Include for I2C_SMBUS_BLOCK_MAX
34#include <linux/i2c.h>
35}
36
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053037constexpr size_t fruBlockSize = 8;
38
Kumar Thangavelc74e7512022-02-03 22:53:05 +053039using DeviceMap = boost::container::flat_map<int, std::vector<uint8_t>>;
40using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
41
Ed Tanousfc171422024-04-04 17:18:16 -070042// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Kumar Thangavelc74e7512022-02-03 22:53:05 +053043inline BusMap busMap;
44
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053045enum class DecodeState
46{
47 ok,
48 end,
49 err,
50};
51
52enum class resCodes
53{
54 resOK,
55 resWarn,
56 resErr
57};
58
Patrick Ventureab296412020-12-30 13:39:37 -080059enum class fruAreas
60{
61 fruAreaInternal = 0,
62 fruAreaChassis,
63 fruAreaBoard,
64 fruAreaProduct,
65 fruAreaMultirecord
66};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053067
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053068struct FruArea
69{
70 size_t start; // Fru Area Start offset
71 size_t size; // Fru Area Size
72 size_t end; // Fru Area end offset
73 size_t updateFieldLoc; // Fru Area update Field Location
Kumar Thangavel51b557b2022-09-13 13:40:47 +053074 size_t restFieldsLoc; // Starting location of restFRUArea data
75 size_t restFieldsEnd; // Ending location of restFRUArea data
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053076};
77
Ed Tanous07d467b2021-02-23 14:48:37 -080078const std::vector<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
79 "PRODUCT", "MULTIRECORD"};
80const std::regex nonAsciiRegex("[^\x01-\x7f]");
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053081
Ed Tanous07d467b2021-02-23 14:48:37 -080082const std::vector<std::string> chassisFruAreas = {"PART_NUMBER",
83 "SERIAL_NUMBER"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053084
Patrick Williamsb7077432024-08-16 15:22:21 -040085const std::vector<std::string> boardFruAreas = {
86 "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
87 "FRU_VERSION_ID"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053088
Ed Tanous07d467b2021-02-23 14:48:37 -080089const std::vector<std::string> productFruAreas = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053090 "MANUFACTURER", "PRODUCT_NAME", "PART_NUMBER", "VERSION",
91 "SERIAL_NUMBER", "ASSET_TAG", "FRU_VERSION_ID"};
92
Ed Tanous07d467b2021-02-23 14:48:37 -080093const std::string fruCustomFieldName = "INFO_AM";
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053094
Patrick Ventureab296412020-12-30 13:39:37 -080095inline fruAreas operator++(fruAreas& x)
96{
Patrick Williamsb7077432024-08-16 15:22:21 -040097 return x = static_cast<fruAreas>(
98 std::underlying_type<fruAreas>::type(x) + 1);
Patrick Ventureab296412020-12-30 13:39:37 -080099}
100
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530101inline const std::string& getFruAreaName(fruAreas area)
102{
Ed Tanous07d467b2021-02-23 14:48:37 -0800103 return fruAreaNames[static_cast<unsigned int>(area)];
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530104}
105
Delphine CC Chiua3ca14a2024-03-27 17:02:24 +0800106std::tm intelEpoch();
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530107
108char sixBitToChar(uint8_t val);
109
110/* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */
Ed Tanous3013fb42022-07-09 08:27:06 -0700111constexpr std::array<char, 6> bcdHighChars = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530112 ' ', '-', '.', 'X', 'X', 'X',
113};
114
115char bcdPlusToChar(uint8_t val);
116
117bool verifyOffset(const std::vector<uint8_t>& fruBytes, fruAreas currentArea,
118 uint8_t len);
119
Patrick Williamsb7077432024-08-16 15:22:21 -0400120std::pair<DecodeState, std::string> decodeFRUData(
121 std::vector<uint8_t>::const_iterator& iter,
122 const std::vector<uint8_t>::const_iterator& end, bool isLangEng);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530123
124bool checkLangEng(uint8_t lang);
125
126resCodes
Michael Shen0961b112022-02-22 11:06:33 +0800127 formatIPMIFRU(const std::vector<uint8_t>& fruBytes,
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030128 boost::container::flat_map<std::string, std::string>& result);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530129
krishnar4213ee212022-11-11 15:39:30 +0530130std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530131
132uint8_t calculateChecksum(std::vector<uint8_t>::const_iterator iter,
133 std::vector<uint8_t>::const_iterator end);
134
135uint8_t calculateChecksum(std::vector<uint8_t>& fruAreaData);
136
Patrick Williamsb7077432024-08-16 15:22:21 -0400137unsigned int updateFRUAreaLenAndChecksum(
138 std::vector<uint8_t>& fruData, size_t fruAreaStart,
139 size_t fruAreaEndOfFieldsOffset, size_t fruAreaEndOffset);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530140
141ssize_t getFieldLength(uint8_t fruFieldTypeLenValue);
142
Oskar Senftbd4075f2021-10-05 23:42:43 -0400143/// \brief Find a FRU header.
Zev Weiss309c0b12022-02-25 01:44:12 +0000144/// \param reader the FRUReader to read via
Oskar Senftbd4075f2021-10-05 23:42:43 -0400145/// \param errorHelp and a helper string for failures
146/// \param blockData buffer to return the last read block
147/// \param baseOffset the offset to start the search at;
148/// set to 0 to perform search;
149/// returns the offset at which a header was found
150/// \return whether a header was found
Zev Weiss309c0b12022-02-25 01:44:12 +0000151bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
Oskar Senftbd4075f2021-10-05 23:42:43 -0400152 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData,
Zev Weiss1525e852022-03-22 22:27:43 +0000153 off_t& baseOffset);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400154
Patrick Ventureab296412020-12-30 13:39:37 -0800155/// \brief Read and validate FRU contents.
Zev Weiss309c0b12022-02-25 01:44:12 +0000156/// \param reader the FRUReader to read via
Patrick Ventureab296412020-12-30 13:39:37 -0800157/// \param errorHelp and a helper string for failures
Marvin Drees2b3ed302023-04-14 16:35:14 +0200158/// \return the FRU contents from the file and bool indicating if the FRU Header
159/// was found
160std::pair<std::vector<uint8_t>, bool>
161 readFRUContents(FRUReader& reader, const std::string& errorHelp);
Patrick Ventureab296412020-12-30 13:39:37 -0800162
163/// \brief Validate an IPMI FRU common header
164/// \param blockData the bytes comprising the common header
165/// \return true if valid
166bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData);
167
168/// \brief Get offset for a common header area
169/// \param area - the area
170/// \return the field offset
171unsigned int getHeaderAreaFieldOffset(fruAreas area);
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530172
173/// \brief Iterate fruArea Names and find offset/location and fields and size of
174/// properties
175/// \param fruData - vector to store fru data
176/// \param propertyName - fru property Name
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530177/// \param fruAreaParams - struct to have fru Area parameters like length,
178/// size.
179/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
180/// Start, Size, End are updated with fruArea and field info.
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530181bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
182 const std::string& propertyName,
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530183 struct FruArea& fruAreaParams);
184
185/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
186/// restFRUAreaField is the rest of the fields in FRU area after the field that
187/// is being updated.
188/// \param fruData - vector to store fru data
189/// \param propertyName - fru property Name
190/// \param fruAreaParams - struct to have fru Area parameters like length
191/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
192/// properties.
193/// \return true on success false on failure. restFieldLoc and restFieldEnd
194/// are updated.
Kumar Thangavel9f2162a2022-08-10 18:05:20 +0530195
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530196bool copyRestFRUArea(std::vector<uint8_t>& fruData,
197 const std::string& propertyName,
198 struct FruArea& fruAreaParams,
199 std::vector<uint8_t>& restFRUAreaFieldsData);
Kumar Thangaveld79d0252022-08-24 14:26:01 +0530200
201/// \brief Get all device dbus path and match path with product name using
202/// regular expression and find the device index for all devices.
203/// \param dbusInterfaceMap - Map to store fru device dbus path and interface
204/// \param productName - fru device product name.
205/// \return optional<int> highest index for fru device on success, return
206/// nullopt on failure.
207std::optional<int> findIndexForFRU(
208 boost::container::flat_map<
209 std::pair<size_t, size_t>,
210 std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
211 std::string& productName);
Kumar Thangavel9f2162a2022-08-10 18:05:20 +0530212
213/// \brief It does format fru data and find productName in the formatted
214/// fru data and return productName.
215/// \param device - vector that contains device list
216/// \param formattedFRU - map that contains formatted FRU data
217/// \param bus - bus number of the device
218/// \param address - address of the device
219/// \param unknownBusObjectCount - Unknown Bus object counter variable
220/// \return optional string. it returns productName or NULL
221
222std::optional<std::string> getProductName(
223 std::vector<uint8_t>& device,
224 boost::container::flat_map<std::string, std::string>& formattedFRU,
225 uint32_t bus, uint32_t address, size_t& unknownBusObjectCount);
Kumar Thangavel9d6f5902022-08-26 16:52:14 +0530226
227bool getFruData(std::vector<uint8_t>& fruData, uint32_t bus, uint32_t address);