xref: /openbmc/openpower-vpd-parser/vpd-manager/src/single_fab.cpp (revision c4fa618189bc05dde54b59d490bf9e83c2513c20)
1 #include "config.h"
2 
3 #include "single_fab.hpp"
4 
5 #include "constants.hpp"
6 #include "event_logger.hpp"
7 #include "parser.hpp"
8 #include "types.hpp"
9 
10 #include <nlohmann/json.hpp>
11 #include <utility/common_utility.hpp>
12 #include <utility/json_utility.hpp>
13 #include <utility/vpd_specific_utility.hpp>
14 
15 namespace vpd
16 {
17 constexpr auto pimPersistVsbpPath =
18     "/var/lib/phosphor-inventory-manager/xyz/openbmc_project/inventory/system/chassis/motherboard/com.ibm.ipzvpd.VSBP";
19 constexpr auto IM_SIZE_IN_BYTES = 0x04;
20 constexpr auto IM_KW_VALUE_OFFSET = 0x000005fb;
21 
getImFromPersistedLocation() const22 std::string SingleFab::getImFromPersistedLocation() const noexcept
23 {
24     try
25     {
26         uint16_t l_errCode = 0;
27         auto l_parsedVsbpJsonObj =
28             jsonUtility::getParsedJson(pimPersistVsbpPath, l_errCode);
29 
30         if (l_errCode)
31         {
32             throw JsonException(
33                 "Failed to parse JSON file [ " +
34                     std::string(pimPersistVsbpPath) +
35                     " ], error : " + commonUtility::getErrCodeMsg(l_errCode),
36                 pimPersistVsbpPath);
37         }
38 
39         if (!l_parsedVsbpJsonObj.contains("value0") ||
40             !l_parsedVsbpJsonObj["value0"].contains(constants::kwdIM) ||
41             !l_parsedVsbpJsonObj["value0"][constants::kwdIM].is_array())
42         {
43             throw std::runtime_error("Mandatory tag(s) missing from JSON");
44         }
45 
46         const types::BinaryVector l_imValue =
47             l_parsedVsbpJsonObj["value0"][constants::kwdIM]
48                 .get<types::BinaryVector>();
49 
50         std::ostringstream l_imData;
51         for (const auto& l_byte : l_imValue)
52         {
53             l_imData << std::setw(2) << std::setfill('0') << std::hex
54                      << static_cast<int>(l_byte);
55         }
56         return l_imData.str();
57     }
58     catch (const std::exception& l_ex)
59     {}
60 
61     return std::string();
62 }
63 
getImFromPlanar() const64 std::string SingleFab::getImFromPlanar() const noexcept
65 {
66     try
67     {
68         const std::string l_systemPlanarPath(SYSTEM_VPD_FILE_PATH);
69         Parser l_parserObj(l_systemPlanarPath, nlohmann::json{});
70 
71         std::shared_ptr<ParserInterface> l_vpdParserInstance =
72             l_parserObj.getVpdParserInstance();
73 
74         auto l_readValue = l_vpdParserInstance->readKeywordFromHardware(
75             std::make_tuple(constants::recVSBP, constants::kwdIM));
76 
77         if (auto l_keywordValue =
78                 std::get_if<types::BinaryVector>(&l_readValue);
79             l_keywordValue && !l_keywordValue->empty())
80         {
81             std::ostringstream l_imData;
82             for (const auto& l_byte : *l_keywordValue)
83             {
84                 l_imData << std::setw(2) << std::setfill('0') << std::hex
85                          << static_cast<int>(l_byte);
86             }
87 
88             return l_imData.str();
89         }
90     }
91     catch (const std::ifstream::failure& l_ex)
92     {}
93 
94     return std::string();
95 }
96 
setImOnPlanar(const std::string & i_imValue) const97 bool SingleFab::setImOnPlanar(const std::string& i_imValue) const noexcept
98 {
99     try
100     {
101         types::BinaryVector l_imValue;
102         const std::string l_systemPlanarEepromPath = SYSTEM_VPD_FILE_PATH;
103 
104         // Convert string to vector of bytes
105         for (auto l_value : i_imValue | std::views::chunk(2))
106         {
107             std::string l_byteString(l_value.begin(), l_value.end());
108             l_imValue.push_back(
109                 static_cast<uint8_t>(std::stoi(l_byteString, nullptr, 16)));
110         }
111 
112         std::shared_ptr<Parser> l_parserObj = std::make_shared<Parser>(
113             l_systemPlanarEepromPath, nlohmann::json{});
114 
115         int l_bytes_updated = l_parserObj->updateVpdKeywordOnHardware(
116             std::make_tuple(constants::recVSBP, constants::kwdIM, l_imValue));
117 
118         return l_bytes_updated > 0 ? true : false;
119     }
120     catch (const std::exception& l_ex)
121     {
122         return false;
123     }
124 }
125 
updateSystemImValueInVpdToP11Series(std::string i_currentImValuePlanar) const126 void SingleFab::updateSystemImValueInVpdToP11Series(
127     std::string i_currentImValuePlanar) const noexcept
128 {
129     bool l_retVal{false};
130     if (!i_currentImValuePlanar.empty())
131     {
132         if (i_currentImValuePlanar.compare(
133                 constants::VALUE_4, constants::VALUE_1,
134                 std::to_string(constants::VALUE_3)) ==
135             constants::STR_CMP_SUCCESS)
136         {
137             i_currentImValuePlanar.replace(constants::VALUE_4,
138                                            constants::VALUE_1,
139                                            std::to_string(constants::VALUE_2));
140         }
141 
142         // update the IM value to P11 series(6000x). Replace the first character
143         // of IM value string with '6'
144         l_retVal = setImOnPlanar(i_currentImValuePlanar.replace(
145             constants::VALUE_0, constants::VALUE_1,
146             std::to_string(constants::VALUE_6)));
147     }
148 
149     if (!l_retVal)
150     {
151         EventLogger::createSyncPel(
152             types::ErrorType::InternalFailure,
153             types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
154             std::string("Failed to update IM value to P11 series."),
155             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
156     }
157 }
158 
singleFabImOverride() const159 int SingleFab::singleFabImOverride() const noexcept
160 {
161     const std::string& l_planarImValue = getImFromPlanar();
162     const std::string& l_eBmcImValue = getImFromPersistedLocation();
163     const bool& l_isFieldModeEnabled = commonUtility::isFieldModeEnabled();
164     const bool& l_isLabModeEnabled =
165         !l_isFieldModeEnabled;                       // used for understanding
166     const bool& l_isPowerVsImage = vpdSpecificUtility::isPowerVsImage();
167     const bool& l_isNormalImage = !l_isPowerVsImage; // used for understanding
168 
169     if (!isValidImSeries(l_planarImValue))
170     {
171         // Create Errorlog for invalid IM series encountered
172         EventLogger::createSyncPel(
173             types::ErrorType::InvalidSystem, types::SeverityType::Error,
174             __FILE__, __FUNCTION__, 0,
175             std::string("Invalid IM found on the system planar, IM value : ") +
176                 l_planarImValue,
177             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
178 
179         return constants::SUCCESS;
180     }
181 
182     if (!l_eBmcImValue.empty())
183     {
184         if (isP10System(l_eBmcImValue))
185         {
186             if (isP10System(l_planarImValue))
187             {
188                 if (l_isFieldModeEnabled && l_isNormalImage)
189                 {
190                     EventLogger::createSyncPel(
191                         types::ErrorType::SystemTypeMismatch,
192                         types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
193                         std::string("Mismatch in IM value found eBMC IM [") +
194                             l_eBmcImValue + std::string("] planar IM [") +
195                             l_planarImValue +
196                             std::string("] Field mode enabled [") +
197                             ((l_isFieldModeEnabled) ? "true" : "false") +
198                             std::string("]"),
199                         std::nullopt, std::nullopt, std::nullopt, std::nullopt);
200 
201                     return constants::FAILURE;
202                 }
203             }
204             else if (isP11System(l_planarImValue))
205             {
206                 if (!(l_isLabModeEnabled && l_isNormalImage))
207                 {
208                     EventLogger::createSyncPel(
209                         types::ErrorType::SystemTypeMismatch,
210                         types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
211                         std::string("Mismatch in IM value found eBMC IM [") +
212                             l_eBmcImValue + std::string("] planar IM [") +
213                             l_planarImValue +
214                             std::string("] Field mode enabled [") +
215                             ((l_isFieldModeEnabled) ? "true" : "false") +
216                             std::string("]"),
217                         std::nullopt, std::nullopt, std::nullopt, std::nullopt);
218 
219                     return constants::FAILURE;
220                 }
221             }
222         }
223         else if (isP11System(l_eBmcImValue))
224         {
225             if (l_isPowerVsImage)
226             {
227                 EventLogger::createSyncPel(
228                     types::ErrorType::SystemTypeMismatch,
229                     types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
230                     std::string("Mismatch in IM value found eBMC IM [") +
231                         l_eBmcImValue + std::string("] planar IM [") +
232                         l_planarImValue +
233                         std::string("] Field mode enabled [") +
234                         ((l_isFieldModeEnabled) ? "true" : "false") +
235                         std::string("]"),
236                     std::nullopt, std::nullopt, std::nullopt, std::nullopt);
237 
238                 return constants::FAILURE;
239             }
240             else
241             {
242                 if (isP10System(l_planarImValue))
243                 {
244                     updateSystemImValueInVpdToP11Series(l_planarImValue);
245                 }
246             }
247         }
248     }
249     else
250     {
251         if (isP11System(l_planarImValue) && l_isPowerVsImage)
252         {
253             EventLogger::createSyncPel(
254                 types::ErrorType::SystemTypeMismatch,
255                 types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
256                 std::string("Mismatch in IM value found eBMC IM [") +
257                     l_eBmcImValue + std::string("] planar IM [") +
258                     l_planarImValue + std::string("] Field mode enabled [") +
259                     ((l_isFieldModeEnabled) ? "true" : "false") +
260                     std::string("]"),
261                 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
262 
263             return constants::FAILURE;
264         }
265         else if (isP10System(l_planarImValue) && l_isNormalImage)
266         {
267             if (l_isLabModeEnabled)
268             {
269                 EventLogger::createSyncPel(
270                     types::ErrorType::UnknownSystemSettings,
271                     types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
272                     std::string("Mismatch in IM value found eBMC IM [") +
273                         l_eBmcImValue + std::string("] planar IM [") +
274                         l_planarImValue +
275                         std::string("] Field mode enabled [") +
276                         ((l_isFieldModeEnabled) ? "true" : "false") +
277                         std::string("]"),
278                     std::nullopt, std::nullopt, std::nullopt, std::nullopt);
279             }
280             else
281             {
282                 updateSystemImValueInVpdToP11Series(l_planarImValue);
283             }
284         }
285     }
286     return constants::SUCCESS;
287 }
288 } // namespace vpd
289