blob: 20d1b663b99432f246440e12e892a453981875b2 [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>
25#include <functional>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053026#include <regex>
Patrick Ventureab296412020-12-30 13:39:37 -080027#include <string>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053028#include <utility>
Patrick Ventureab296412020-12-30 13:39:37 -080029#include <vector>
Patrick Ventureab296412020-12-30 13:39:37 -080030extern "C"
31{
32// Include for I2C_SMBUS_BLOCK_MAX
33#include <linux/i2c.h>
34}
35
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053036constexpr size_t fruBlockSize = 8;
37
Kumar Thangavelc74e7512022-02-03 22:53:05 +053038using DeviceMap = boost::container::flat_map<int, std::vector<uint8_t>>;
39using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
40
41inline BusMap busMap;
42
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053043enum class DecodeState
44{
45 ok,
46 end,
47 err,
48};
49
50enum class resCodes
51{
52 resOK,
53 resWarn,
54 resErr
55};
56
Patrick Ventureab296412020-12-30 13:39:37 -080057enum class fruAreas
58{
59 fruAreaInternal = 0,
60 fruAreaChassis,
61 fruAreaBoard,
62 fruAreaProduct,
63 fruAreaMultirecord
64};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053065
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053066struct FruArea
67{
68 size_t start; // Fru Area Start offset
69 size_t size; // Fru Area Size
70 size_t end; // Fru Area end offset
71 size_t updateFieldLoc; // Fru Area update Field Location
Kumar Thangavel51b557b2022-09-13 13:40:47 +053072 size_t restFieldsLoc; // Starting location of restFRUArea data
73 size_t restFieldsEnd; // Ending location of restFRUArea data
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053074};
75
Ed Tanous07d467b2021-02-23 14:48:37 -080076const std::vector<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
77 "PRODUCT", "MULTIRECORD"};
78const std::regex nonAsciiRegex("[^\x01-\x7f]");
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053079
Ed Tanous07d467b2021-02-23 14:48:37 -080080const std::vector<std::string> chassisFruAreas = {"PART_NUMBER",
81 "SERIAL_NUMBER"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053082
Ed Tanous07d467b2021-02-23 14:48:37 -080083const std::vector<std::string> boardFruAreas = {"MANUFACTURER", "PRODUCT_NAME",
84 "SERIAL_NUMBER", "PART_NUMBER",
85 "FRU_VERSION_ID"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053086
Ed Tanous07d467b2021-02-23 14:48:37 -080087const std::vector<std::string> productFruAreas = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053088 "MANUFACTURER", "PRODUCT_NAME", "PART_NUMBER", "VERSION",
89 "SERIAL_NUMBER", "ASSET_TAG", "FRU_VERSION_ID"};
90
Ed Tanous07d467b2021-02-23 14:48:37 -080091const std::string fruCustomFieldName = "INFO_AM";
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053092
Patrick Ventureab296412020-12-30 13:39:37 -080093inline fruAreas operator++(fruAreas& x)
94{
95 return x = static_cast<fruAreas>(std::underlying_type<fruAreas>::type(x) +
96 1);
97}
98
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053099inline const std::string& getFruAreaName(fruAreas area)
100{
Ed Tanous07d467b2021-02-23 14:48:37 -0800101 return fruAreaNames[static_cast<unsigned int>(area)];
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530102}
103
Ed Tanous07d467b2021-02-23 14:48:37 -0800104std::tm intelEpoch(void);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530105
106char sixBitToChar(uint8_t val);
107
108/* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */
Ed Tanous3013fb42022-07-09 08:27:06 -0700109constexpr std::array<char, 6> bcdHighChars = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530110 ' ', '-', '.', 'X', 'X', 'X',
111};
112
113char bcdPlusToChar(uint8_t val);
114
115bool verifyOffset(const std::vector<uint8_t>& fruBytes, fruAreas currentArea,
116 uint8_t len);
117
118std::pair<DecodeState, std::string>
119 decodeFRUData(std::vector<uint8_t>::const_iterator& iter,
120 const std::vector<uint8_t>::const_iterator& end,
121 bool isLangEng);
122
123bool checkLangEng(uint8_t lang);
124
125resCodes
Michael Shen0961b112022-02-22 11:06:33 +0800126 formatIPMIFRU(const std::vector<uint8_t>& fruBytes,
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030127 boost::container::flat_map<std::string, std::string>& result);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530128
krishnar4213ee212022-11-11 15:39:30 +0530129std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530130
131uint8_t calculateChecksum(std::vector<uint8_t>::const_iterator iter,
132 std::vector<uint8_t>::const_iterator end);
133
134uint8_t calculateChecksum(std::vector<uint8_t>& fruAreaData);
135
136unsigned int updateFRUAreaLenAndChecksum(std::vector<uint8_t>& fruData,
137 size_t fruAreaStart,
138 size_t fruAreaEndOfFieldsOffset,
139 size_t fruAreaEndOffset);
140
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
158/// \return the FRU contents from the file
Zev Weiss309c0b12022-02-25 01:44:12 +0000159std::vector<uint8_t> readFRUContents(FRUReader& reader,
Patrick Ventureab296412020-12-30 13:39:37 -0800160 const std::string& errorHelp);
161
162/// \brief Validate an IPMI FRU common header
163/// \param blockData the bytes comprising the common header
164/// \return true if valid
165bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData);
166
167/// \brief Get offset for a common header area
168/// \param area - the area
169/// \return the field offset
170unsigned int getHeaderAreaFieldOffset(fruAreas area);
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530171
172/// \brief Iterate fruArea Names and find offset/location and fields and size of
173/// properties
174/// \param fruData - vector to store fru data
175/// \param propertyName - fru property Name
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530176/// \param fruAreaParams - struct to have fru Area parameters like length,
177/// size.
178/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
179/// Start, Size, End are updated with fruArea and field info.
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530180bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
181 const std::string& propertyName,
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530182 struct FruArea& fruAreaParams);
183
184/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
185/// restFRUAreaField is the rest of the fields in FRU area after the field that
186/// is being updated.
187/// \param fruData - vector to store fru data
188/// \param propertyName - fru property Name
189/// \param fruAreaParams - struct to have fru Area parameters like length
190/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
191/// properties.
192/// \return true on success false on failure. restFieldLoc and restFieldEnd
193/// are updated.
194bool copyRestFRUArea(std::vector<uint8_t>& fruData,
195 const std::string& propertyName,
196 struct FruArea& fruAreaParams,
197 std::vector<uint8_t>& restFRUAreaFieldsData);
Kumar Thangaveld79d0252022-08-24 14:26:01 +0530198
199/// \brief Get all device dbus path and match path with product name using
200/// regular expression and find the device index for all devices.
201/// \param dbusInterfaceMap - Map to store fru device dbus path and interface
202/// \param productName - fru device product name.
203/// \return optional<int> highest index for fru device on success, return
204/// nullopt on failure.
205std::optional<int> findIndexForFRU(
206 boost::container::flat_map<
207 std::pair<size_t, size_t>,
208 std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
209 std::string& productName);