-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathfru_utils.hpp
227 lines (186 loc) · 7.78 KB
/
fru_utils.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
/// \file fru_utils.hpp
#pragma once
#include "fru_reader.hpp"
#include <boost/container/flat_map.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <regex>
#include <string>
#include <utility>
#include <vector>
extern "C"
{
// Include for I2C_SMBUS_BLOCK_MAX
#include <linux/i2c.h>
}
constexpr size_t fruBlockSize = 8;
using DeviceMap = boost::container::flat_map<int, std::vector<uint8_t>>;
using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
// 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<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
"PRODUCT", "MULTIRECORD"};
const std::regex nonAsciiRegex("[^\x01-\x7f]");
const std::vector<std::string> chassisFruAreas = {"PART_NUMBER",
"SERIAL_NUMBER"};
const std::vector<std::string> boardFruAreas = {
"MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
"FRU_VERSION_ID"};
const std::vector<std::string> 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<fruAreas>(
std::underlying_type<fruAreas>::type(x) + 1);
}
inline const std::string& getFruAreaName(fruAreas area)
{
return fruAreaNames[static_cast<unsigned int>(area)];
}
std::tm intelEpoch();
char sixBitToChar(uint8_t val);
/* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */
constexpr std::array<char, 6> bcdHighChars = {
' ', '-', '.', 'X', 'X', 'X',
};
char bcdPlusToChar(uint8_t val);
bool verifyOffset(const std::vector<uint8_t>& fruBytes, fruAreas currentArea,
uint8_t len);
std::pair<DecodeState, std::string> decodeFRUData(
std::vector<uint8_t>::const_iterator& iter,
const std::vector<uint8_t>::const_iterator& end, bool isLangEng);
bool checkLangEng(uint8_t lang);
resCodes formatIPMIFRU(
const std::vector<uint8_t>& fruBytes,
boost::container::flat_map<std::string, std::string>& result);
std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address);
uint8_t calculateChecksum(std::vector<uint8_t>::const_iterator iter,
std::vector<uint8_t>::const_iterator end);
uint8_t calculateChecksum(std::vector<uint8_t>& fruAreaData);
unsigned int updateFRUAreaLenAndChecksum(
std::vector<uint8_t>& 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<uint8_t, I2C_SMBUS_BLOCK_MAX>& 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<std::vector<uint8_t>, 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<uint8_t, I2C_SMBUS_BLOCK_MAX>& 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<uint8_t>& 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<uint8_t>& fruData,
const std::string& propertyName,
struct FruArea& fruAreaParams,
std::vector<uint8_t>& 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<int> highest index for fru device on success, return
/// nullopt on failure.
std::optional<int> findIndexForFRU(
boost::container::flat_map<
std::pair<size_t, size_t>,
std::shared_ptr<sdbusplus::asio::dbus_interface>>& 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<std::string> getProductName(
std::vector<uint8_t>& device,
boost::container::flat_map<std::string, std::string>& formattedFRU,
uint32_t bus, uint32_t address, size_t& unknownBusObjectCount);
bool getFruData(std::vector<uint8_t>& fruData, uint32_t bus, uint32_t address);