blob: d689d5caa7814acecf8f3020bd4cfa7f009e80fb [file] [log] [blame]
Alexander Hansen4e1142d2025-07-25 17:07:27 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Patrick Ventureab296412020-12-30 13:39:37 -08003
4#pragma once
Zev Weiss309c0b12022-02-25 01:44:12 +00005#include "fru_reader.hpp"
Ed Tanous3013fb42022-07-09 08:27:06 -07006
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +05307#include <boost/container/flat_map.hpp>
Kumar Thangaveld79d0252022-08-24 14:26:01 +05308#include <sdbusplus/asio/object_server.hpp>
Patrick Ventureab296412020-12-30 13:39:37 -08009
10#include <cstdint>
Patrick Williamsb9a1f962024-07-13 16:34:49 -050011#include <cstdio>
Patrick Ventureab296412020-12-30 13:39:37 -080012#include <functional>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053013#include <regex>
Patrick Ventureab296412020-12-30 13:39:37 -080014#include <string>
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053015#include <utility>
Patrick Ventureab296412020-12-30 13:39:37 -080016#include <vector>
Patrick Ventureab296412020-12-30 13:39:37 -080017extern "C"
18{
19// Include for I2C_SMBUS_BLOCK_MAX
20#include <linux/i2c.h>
21}
22
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053023constexpr size_t fruBlockSize = 8;
24
Kumar Thangavelc74e7512022-02-03 22:53:05 +053025using DeviceMap = boost::container::flat_map<int, std::vector<uint8_t>>;
26using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
27
Ed Tanousfc171422024-04-04 17:18:16 -070028// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Kumar Thangavelc74e7512022-02-03 22:53:05 +053029inline BusMap busMap;
30
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053031enum class DecodeState
32{
33 ok,
34 end,
35 err,
36};
37
38enum class resCodes
39{
40 resOK,
41 resWarn,
42 resErr
43};
44
Patrick Ventureab296412020-12-30 13:39:37 -080045enum class fruAreas
46{
47 fruAreaInternal = 0,
48 fruAreaChassis,
49 fruAreaBoard,
50 fruAreaProduct,
51 fruAreaMultirecord
52};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053053
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053054struct FruArea
55{
56 size_t start; // Fru Area Start offset
57 size_t size; // Fru Area Size
58 size_t end; // Fru Area end offset
59 size_t updateFieldLoc; // Fru Area update Field Location
Kumar Thangavel51b557b2022-09-13 13:40:47 +053060 size_t restFieldsLoc; // Starting location of restFRUArea data
61 size_t restFieldsEnd; // Ending location of restFRUArea data
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +053062};
63
Ed Tanous07d467b2021-02-23 14:48:37 -080064const std::vector<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
65 "PRODUCT", "MULTIRECORD"};
66const std::regex nonAsciiRegex("[^\x01-\x7f]");
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053067
Ed Tanous07d467b2021-02-23 14:48:37 -080068const std::vector<std::string> chassisFruAreas = {"PART_NUMBER",
69 "SERIAL_NUMBER"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053070
Patrick Williamsb7077432024-08-16 15:22:21 -040071const std::vector<std::string> boardFruAreas = {
72 "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
73 "FRU_VERSION_ID"};
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053074
Ed Tanous07d467b2021-02-23 14:48:37 -080075const std::vector<std::string> productFruAreas = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053076 "MANUFACTURER", "PRODUCT_NAME", "PART_NUMBER", "VERSION",
77 "SERIAL_NUMBER", "ASSET_TAG", "FRU_VERSION_ID"};
78
Ed Tanous07d467b2021-02-23 14:48:37 -080079const std::string fruCustomFieldName = "INFO_AM";
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053080
Patrick Ventureab296412020-12-30 13:39:37 -080081inline fruAreas operator++(fruAreas& x)
82{
Patrick Williamsb7077432024-08-16 15:22:21 -040083 return x = static_cast<fruAreas>(
84 std::underlying_type<fruAreas>::type(x) + 1);
Patrick Ventureab296412020-12-30 13:39:37 -080085}
86
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053087inline const std::string& getFruAreaName(fruAreas area)
88{
Ed Tanous07d467b2021-02-23 14:48:37 -080089 return fruAreaNames[static_cast<unsigned int>(area)];
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053090}
91
Delphine CC Chiua3ca14a2024-03-27 17:02:24 +080092std::tm intelEpoch();
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053093
94char sixBitToChar(uint8_t val);
95
96/* 0xd - 0xf are reserved values, but not fatal; use a placeholder char. */
Ed Tanous3013fb42022-07-09 08:27:06 -070097constexpr std::array<char, 6> bcdHighChars = {
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +053098 ' ', '-', '.', 'X', 'X', 'X',
99};
100
101char bcdPlusToChar(uint8_t val);
102
Ed Tanous23e3f452025-04-08 10:37:56 -0700103bool verifyOffset(std::span<const uint8_t> fruBytes, fruAreas currentArea,
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530104 uint8_t len);
105
Patrick Williamsb7077432024-08-16 15:22:21 -0400106std::pair<DecodeState, std::string> decodeFRUData(
Ed Tanous23e3f452025-04-08 10:37:56 -0700107 std::span<const uint8_t>::const_iterator& iter,
108 std::span<const uint8_t>::const_iterator& end, bool isLangEng);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530109
110bool checkLangEng(uint8_t lang);
111
Patrick Williams5a807032025-03-03 11:20:39 -0500112resCodes formatIPMIFRU(
Ed Tanous23e3f452025-04-08 10:37:56 -0700113 std::span<const uint8_t> fruBytes,
Patrick Williams5a807032025-03-03 11:20:39 -0500114 boost::container::flat_map<std::string, std::string>& result);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530115
krishnar4213ee212022-11-11 15:39:30 +0530116std::vector<uint8_t>& getFRUInfo(const uint16_t& bus, const uint8_t& address);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530117
Ed Tanous23e3f452025-04-08 10:37:56 -0700118uint8_t calculateChecksum(std::span<const uint8_t>::const_iterator iter,
119 std::span<const uint8_t>::const_iterator end);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530120
Ed Tanous23e3f452025-04-08 10:37:56 -0700121uint8_t calculateChecksum(std::span<const uint8_t> fruAreaData);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530122
Patrick Williamsb7077432024-08-16 15:22:21 -0400123unsigned int updateFRUAreaLenAndChecksum(
124 std::vector<uint8_t>& fruData, size_t fruAreaStart,
125 size_t fruAreaEndOfFieldsOffset, size_t fruAreaEndOffset);
Kumar Thangavelc8dc4af2021-01-12 10:36:38 +0530126
127ssize_t getFieldLength(uint8_t fruFieldTypeLenValue);
128
Ed Tanous10c57652025-09-30 10:24:57 -0700129struct FruSections
130{
131 off_t IpmiFruOffset = 0;
132 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> ipmiFruBlock;
133
134 off_t GigabyteXmlOffset = 0;
135};
136
Oskar Senftbd4075f2021-10-05 23:42:43 -0400137/// \brief Find a FRU header.
Zev Weiss309c0b12022-02-25 01:44:12 +0000138/// \param reader the FRUReader to read via
Oskar Senftbd4075f2021-10-05 23:42:43 -0400139/// \param errorHelp and a helper string for failures
140/// \param blockData buffer to return the last read block
141/// \param baseOffset the offset to start the search at;
142/// set to 0 to perform search;
143/// returns the offset at which a header was found
144/// \return whether a header was found
Ed Tanous10c57652025-09-30 10:24:57 -0700145std::optional<FruSections> findFRUHeader(
146 FRUReader& reader, const std::string& errorHelp, off_t offset);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400147
Patrick Ventureab296412020-12-30 13:39:37 -0800148/// \brief Read and validate FRU contents.
Zev Weiss309c0b12022-02-25 01:44:12 +0000149/// \param reader the FRUReader to read via
Patrick Ventureab296412020-12-30 13:39:37 -0800150/// \param errorHelp and a helper string for failures
Marvin Drees2b3ed302023-04-14 16:35:14 +0200151/// \return the FRU contents from the file and bool indicating if the FRU Header
152/// was found
Patrick Williams5a807032025-03-03 11:20:39 -0500153std::pair<std::vector<uint8_t>, bool> readFRUContents(
154 FRUReader& reader, const std::string& errorHelp);
Patrick Ventureab296412020-12-30 13:39:37 -0800155
156/// \brief Validate an IPMI FRU common header
157/// \param blockData the bytes comprising the common header
158/// \return true if valid
159bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData);
160
161/// \brief Get offset for a common header area
162/// \param area - the area
163/// \return the field offset
164unsigned int getHeaderAreaFieldOffset(fruAreas area);
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530165
166/// \brief Iterate fruArea Names and find offset/location and fields and size of
167/// properties
168/// \param fruData - vector to store fru data
169/// \param propertyName - fru property Name
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530170/// \param fruAreaParams - struct to have fru Area parameters like length,
171/// size.
172/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
173/// Start, Size, End are updated with fruArea and field info.
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530174bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
175 const std::string& propertyName,
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530176 struct FruArea& fruAreaParams);
177
178/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
179/// restFRUAreaField is the rest of the fields in FRU area after the field that
180/// is being updated.
181/// \param fruData - vector to store fru data
182/// \param propertyName - fru property Name
183/// \param fruAreaParams - struct to have fru Area parameters like length
184/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
185/// properties.
186/// \return true on success false on failure. restFieldLoc and restFieldEnd
187/// are updated.
Kumar Thangavel9f2162a2022-08-10 18:05:20 +0530188
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530189bool copyRestFRUArea(std::vector<uint8_t>& fruData,
190 const std::string& propertyName,
191 struct FruArea& fruAreaParams,
192 std::vector<uint8_t>& restFRUAreaFieldsData);
Kumar Thangaveld79d0252022-08-24 14:26:01 +0530193
194/// \brief Get all device dbus path and match path with product name using
195/// regular expression and find the device index for all devices.
196/// \param dbusInterfaceMap - Map to store fru device dbus path and interface
197/// \param productName - fru device product name.
198/// \return optional<int> highest index for fru device on success, return
199/// nullopt on failure.
200std::optional<int> findIndexForFRU(
201 boost::container::flat_map<
202 std::pair<size_t, size_t>,
203 std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
204 std::string& productName);
Kumar Thangavel9f2162a2022-08-10 18:05:20 +0530205
206/// \brief It does format fru data and find productName in the formatted
207/// fru data and return productName.
208/// \param device - vector that contains device list
209/// \param formattedFRU - map that contains formatted FRU data
210/// \param bus - bus number of the device
211/// \param address - address of the device
212/// \param unknownBusObjectCount - Unknown Bus object counter variable
213/// \return optional string. it returns productName or NULL
214
215std::optional<std::string> getProductName(
216 std::vector<uint8_t>& device,
217 boost::container::flat_map<std::string, std::string>& formattedFRU,
218 uint32_t bus, uint32_t address, size_t& unknownBusObjectCount);
Kumar Thangavel9d6f5902022-08-26 16:52:14 +0530219
220bool getFruData(std::vector<uint8_t>& fruData, uint32_t bus, uint32_t address);
Naresh Solanki89092a92025-06-02 15:48:04 +0530221
222bool isFieldEditable(std::string_view fieldName);
Naresh Solankicf288962025-06-06 15:26:11 +0530223
Marc Olberding25680e32025-10-03 12:38:10 -0700224bool updateAreaChecksum(std::vector<uint8_t>& fruArea);
Naresh Solankicf288962025-06-06 15:26:11 +0530225
226bool disassembleFruData(std::vector<uint8_t>& fruData,
227 std::vector<std::vector<uint8_t>>& areasData);
228
229bool createDummyArea(fruAreas fruArea, std::vector<uint8_t>& areaData);
230
231bool assembleFruData(std::vector<uint8_t>& fruData,
232 const std::vector<std::vector<uint8_t>>& areasData);
233
234bool setField(const fruAreas& fruAreaToUpdate, std::vector<uint8_t>& areaData,
235 const std::string& propertyName, const std::string& value);
Marc Olberding9bde15b2025-09-09 15:24:00 -0700236
237bool updateAddProperty(const std::string& propertyValue,
238 const std::string& propertyName,
Ed Tanous10c57652025-09-30 10:24:57 -0700239 std::vector<uint8_t>& fruData);
240
241std::string parseMacFromGzipXmlHeader(FRUReader& reader, off_t offset);