blob: c441a0b84fdd9f4b119fafab49aa348bc34b74bc [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
Oskar Senftbd4075f2021-10-05 23:42:43 -0400129/// \brief Find a FRU header.
Zev Weiss309c0b12022-02-25 01:44:12 +0000130/// \param reader the FRUReader to read via
Oskar Senftbd4075f2021-10-05 23:42:43 -0400131/// \param errorHelp and a helper string for failures
132/// \param blockData buffer to return the last read block
133/// \param baseOffset the offset to start the search at;
134/// set to 0 to perform search;
135/// returns the offset at which a header was found
136/// \return whether a header was found
Zev Weiss309c0b12022-02-25 01:44:12 +0000137bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
Oskar Senftbd4075f2021-10-05 23:42:43 -0400138 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData,
Zev Weiss1525e852022-03-22 22:27:43 +0000139 off_t& baseOffset);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400140
Patrick Ventureab296412020-12-30 13:39:37 -0800141/// \brief Read and validate FRU contents.
Zev Weiss309c0b12022-02-25 01:44:12 +0000142/// \param reader the FRUReader to read via
Patrick Ventureab296412020-12-30 13:39:37 -0800143/// \param errorHelp and a helper string for failures
Marvin Drees2b3ed302023-04-14 16:35:14 +0200144/// \return the FRU contents from the file and bool indicating if the FRU Header
145/// was found
Patrick Williams5a807032025-03-03 11:20:39 -0500146std::pair<std::vector<uint8_t>, bool> readFRUContents(
147 FRUReader& reader, const std::string& errorHelp);
Patrick Ventureab296412020-12-30 13:39:37 -0800148
149/// \brief Validate an IPMI FRU common header
150/// \param blockData the bytes comprising the common header
151/// \return true if valid
152bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData);
153
154/// \brief Get offset for a common header area
155/// \param area - the area
156/// \return the field offset
157unsigned int getHeaderAreaFieldOffset(fruAreas area);
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530158
159/// \brief Iterate fruArea Names and find offset/location and fields and size of
160/// properties
161/// \param fruData - vector to store fru data
162/// \param propertyName - fru property Name
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530163/// \param fruAreaParams - struct to have fru Area parameters like length,
164/// size.
165/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
166/// Start, Size, End are updated with fruArea and field info.
Kumar Thangavelbdfc5ec2022-08-29 22:23:00 +0530167bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
168 const std::string& propertyName,
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530169 struct FruArea& fruAreaParams);
170
171/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
172/// restFRUAreaField is the rest of the fields in FRU area after the field that
173/// is being updated.
174/// \param fruData - vector to store fru data
175/// \param propertyName - fru property Name
176/// \param fruAreaParams - struct to have fru Area parameters like length
177/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
178/// properties.
179/// \return true on success false on failure. restFieldLoc and restFieldEnd
180/// are updated.
Kumar Thangavel9f2162a2022-08-10 18:05:20 +0530181
Kumar Thangavel51b557b2022-09-13 13:40:47 +0530182bool copyRestFRUArea(std::vector<uint8_t>& fruData,
183 const std::string& propertyName,
184 struct FruArea& fruAreaParams,
185 std::vector<uint8_t>& restFRUAreaFieldsData);
Kumar Thangaveld79d0252022-08-24 14:26:01 +0530186
187/// \brief Get all device dbus path and match path with product name using
188/// regular expression and find the device index for all devices.
189/// \param dbusInterfaceMap - Map to store fru device dbus path and interface
190/// \param productName - fru device product name.
191/// \return optional<int> highest index for fru device on success, return
192/// nullopt on failure.
193std::optional<int> findIndexForFRU(
194 boost::container::flat_map<
195 std::pair<size_t, size_t>,
196 std::shared_ptr<sdbusplus::asio::dbus_interface>>& dbusInterfaceMap,
197 std::string& productName);
Kumar Thangavel9f2162a2022-08-10 18:05:20 +0530198
199/// \brief It does format fru data and find productName in the formatted
200/// fru data and return productName.
201/// \param device - vector that contains device list
202/// \param formattedFRU - map that contains formatted FRU data
203/// \param bus - bus number of the device
204/// \param address - address of the device
205/// \param unknownBusObjectCount - Unknown Bus object counter variable
206/// \return optional string. it returns productName or NULL
207
208std::optional<std::string> getProductName(
209 std::vector<uint8_t>& device,
210 boost::container::flat_map<std::string, std::string>& formattedFRU,
211 uint32_t bus, uint32_t address, size_t& unknownBusObjectCount);
Kumar Thangavel9d6f5902022-08-26 16:52:14 +0530212
213bool getFruData(std::vector<uint8_t>& fruData, uint32_t bus, uint32_t address);