blob: 0a988ef2c21a29bd9e029f558334d5d54eebba76 [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>
Patrick Ventureab296412020-12-30 13:39:37 -080022
23#include <cstdint>
24#include <functional>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053025#include <regex>
Patrick Ventureab296412020-12-30 13:39:37 -080026#include <string>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053027#include <utility>
Patrick Ventureab296412020-12-30 13:39:37 -080028#include <vector>
Patrick Ventureab296412020-12-30 13:39:37 -080029extern "C"
30{
31// Include for I2C_SMBUS_BLOCK_MAX
32#include <linux/i2c.h>
33}
34
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053035constexpr size_t fruBlockSize = 8;
36
Kumar Thangavelc74e7512022-02-03 22:53:05 +053037using DeviceMap = boost::container::flat_map<int, std::vector<uint8_t>>;
38using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
39
40inline BusMap busMap;
41
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053042enum class DecodeState
43{
44 ok,
45 end,
46 err,
47};
48
49enum class resCodes
50{
51 resOK,
52 resWarn,
53 resErr
54};
55
Patrick Ventureab296412020-12-30 13:39:37 -080056enum class fruAreas
57{
58 fruAreaInternal = 0,
59 fruAreaChassis,
60 fruAreaBoard,
61 fruAreaProduct,
62 fruAreaMultirecord
63};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053064
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053065struct FruArea
66{
67 size_t start; // Fru Area Start offset
68 size_t size; // Fru Area Size
69 size_t end; // Fru Area end offset
70 size_t updateFieldLoc; // Fru Area update Field Location
Kumar Thangavel51b557b2022-09-13 13:40:47 +053071 size_t restFieldsLoc; // Starting location of restFRUArea data
72 size_t restFieldsEnd; // Ending location of restFRUArea data
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053073};
74
Ed Tanous07d467b2021-02-23 14:48:37 -080075const std::vector<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
76 "PRODUCT", "MULTIRECORD"};
77const std::regex nonAsciiRegex("[^\x01-\x7f]");
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053078
Ed Tanous07d467b2021-02-23 14:48:37 -080079const std::vector<std::string> chassisFruAreas = {"PART_NUMBER",
80 "SERIAL_NUMBER"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053081
Ed Tanous07d467b2021-02-23 14:48:37 -080082const std::vector<std::string> boardFruAreas = {"MANUFACTURER", "PRODUCT_NAME",
83 "SERIAL_NUMBER", "PART_NUMBER",
84 "FRU_VERSION_ID"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053085
Ed Tanous07d467b2021-02-23 14:48:37 -080086const std::vector<std::string> productFruAreas = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053087 "MANUFACTURER", "PRODUCT_NAME", "PART_NUMBER", "VERSION",
88 "SERIAL_NUMBER", "ASSET_TAG", "FRU_VERSION_ID"};
89
Ed Tanous07d467b2021-02-23 14:48:37 -080090const std::string fruCustomFieldName = "INFO_AM";
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053091
Patrick Ventureab296412020-12-30 13:39:37 -080092inline fruAreas operator++(fruAreas& x)
93{
94 return x = static_cast<fruAreas>(std::underlying_type<fruAreas>::type(x) +
95 1);
96}
97
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053098inline const std::string& getFruAreaName(fruAreas area)
99{
Ed Tanous07d467b2021-02-23 14:48:37 -0800100 return fruAreaNames[static_cast<unsigned int>(area)];
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530101}
102
Ed Tanous07d467b2021-02-23 14:48:37 -0800103std::tm intelEpoch(void);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530104
105char sixBitToChar(uint8_t val);
106
107/* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */
Ed Tanous3013fb42022-07-09 08:27:06 -0700108constexpr std::array<char, 6> bcdHighChars = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530109 ' ', '-', '.', 'X', 'X', 'X',
110};
111
112char bcdPlusToChar(uint8_t val);
113
114bool verifyOffset(const std::vector<uint8_t>& fruBytes, fruAreas currentArea,
115 uint8_t len);
116
117std::pair<DecodeState, std::string>
118 decodeFRUData(std::vector<uint8_t>::const_iterator& iter,
119 const std::vector<uint8_t>::const_iterator& end,
120 bool isLangEng);
121
122bool checkLangEng(uint8_t lang);
123
124resCodes
Michael Shen0961b112022-02-22 11:06:33 +0800125 formatIPMIFRU(const std::vector<uint8_t>& fruBytes,
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030126 boost::container::flat_map<std::string, std::string>& result);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530127
krishnar4213ee212022-11-11 15:39:30 +0530128std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530129
130uint8_t calculateChecksum(std::vector<uint8_t>::const_iterator iter,
131 std::vector<uint8_t>::const_iterator end);
132
133uint8_t calculateChecksum(std::vector<uint8_t>& fruAreaData);
134
135unsigned int updateFRUAreaLenAndChecksum(std::vector<uint8_t>& fruData,
136 size_t fruAreaStart,
137 size_t fruAreaEndOfFieldsOffset,
138 size_t fruAreaEndOffset);
139
140ssize_t getFieldLength(uint8_t fruFieldTypeLenValue);
141
Oskar Senftbd4075f2021-10-05 23:42:43 -0400142/// \brief Find a FRU header.
Zev Weiss309c0b12022-02-25 01:44:12 +0000143/// \param reader the FRUReader to read via
Oskar Senftbd4075f2021-10-05 23:42:43 -0400144/// \param errorHelp and a helper string for failures
145/// \param blockData buffer to return the last read block
146/// \param baseOffset the offset to start the search at;
147/// set to 0 to perform search;
148/// returns the offset at which a header was found
149/// \return whether a header was found
Zev Weiss309c0b12022-02-25 01:44:12 +0000150bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
Oskar Senftbd4075f2021-10-05 23:42:43 -0400151 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData,
Zev Weiss1525e852022-03-22 22:27:43 +0000152 off_t& baseOffset);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400153
Patrick Ventureab296412020-12-30 13:39:37 -0800154/// \brief Read and validate FRU contents.
Zev Weiss309c0b12022-02-25 01:44:12 +0000155/// \param reader the FRUReader to read via
Patrick Ventureab296412020-12-30 13:39:37 -0800156/// \param errorHelp and a helper string for failures
157/// \return the FRU contents from the file
Zev Weiss309c0b12022-02-25 01:44:12 +0000158std::vector<uint8_t> readFRUContents(FRUReader& reader,
Patrick Ventureab296412020-12-30 13:39:37 -0800159 const std::string& errorHelp);
160
161/// \brief Validate an IPMI FRU common header
162/// \param blockData the bytes comprising the common header
163/// \return true if valid
164bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData);
165
166/// \brief Get offset for a common header area
167/// \param area - the area
168/// \return the field offset
169unsigned int getHeaderAreaFieldOffset(fruAreas area);
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530170
171/// \brief Iterate fruArea Names and find offset/location and fields and size of
172/// properties
173/// \param fruData - vector to store fru data
174/// \param propertyName - fru property Name
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530175/// \param fruAreaParams - struct to have fru Area parameters like length,
176/// size.
177/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
178/// Start, Size, End are updated with fruArea and field info.
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530179bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
180 const std::string& propertyName,
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530181 struct FruArea& fruAreaParams);
182
183/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
184/// restFRUAreaField is the rest of the fields in FRU area after the field that
185/// is being updated.
186/// \param fruData - vector to store fru data
187/// \param propertyName - fru property Name
188/// \param fruAreaParams - struct to have fru Area parameters like length
189/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
190/// properties.
191/// \return true on success false on failure. restFieldLoc and restFieldEnd
192/// are updated.
193bool copyRestFRUArea(std::vector<uint8_t>& fruData,
194 const std::string& propertyName,
195 struct FruArea& fruAreaParams,
196 std::vector<uint8_t>& restFRUAreaFieldsData);