xref: /openbmc/openpower-vpd-parser/vpd-manager/src/single_fab.cpp (revision c6159a29119d5e08476ed85eaf1cf47ebf9bebdb)
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 
isFieldModeEnabled() const126 bool SingleFab::isFieldModeEnabled() const noexcept
127 {
128     try
129     {
130         std::vector<std::string> l_cmdOutput =
131             commonUtility::executeCmd("/sbin/fw_printenv fieldmode");
132 
133         if (l_cmdOutput.size() > 0)
134         {
135             commonUtility::toLower(l_cmdOutput[0]);
136 
137             // Remove the new line character from the string.
138             l_cmdOutput[0].erase(l_cmdOutput[0].length() - 1);
139 
140             return l_cmdOutput[0] == "fieldmode=true" ? true : false;
141         }
142     }
143     catch (const std::exception& l_ex)
144     {}
145 
146     return false;
147 }
148 
updateSystemImValueInVpdToP11Series(std::string i_currentImValuePlanar) const149 void SingleFab::updateSystemImValueInVpdToP11Series(
150     std::string i_currentImValuePlanar) const noexcept
151 {
152     bool l_retVal{false};
153     if (!i_currentImValuePlanar.empty())
154     {
155         if (i_currentImValuePlanar.compare(
156                 constants::VALUE_4, constants::VALUE_1,
157                 std::to_string(constants::VALUE_3)) ==
158             constants::STR_CMP_SUCCESS)
159         {
160             i_currentImValuePlanar.replace(constants::VALUE_4,
161                                            constants::VALUE_1,
162                                            std::to_string(constants::VALUE_2));
163         }
164 
165         // update the IM value to P11 series(6000x). Replace the first character
166         // of IM value string with '6'
167         l_retVal = setImOnPlanar(i_currentImValuePlanar.replace(
168             constants::VALUE_0, constants::VALUE_1,
169             std::to_string(constants::VALUE_6)));
170     }
171 
172     if (!l_retVal)
173     {
174         EventLogger::createSyncPel(
175             types::ErrorType::InternalFailure,
176             types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
177             std::string("Failed to update IM value to P11 series."),
178             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
179     }
180 }
181 
singleFabImOverride() const182 int SingleFab::singleFabImOverride() const noexcept
183 {
184     const std::string& l_planarImValue = getImFromPlanar();
185     const std::string& l_eBmcImValue = getImFromPersistedLocation();
186     const bool& l_isFieldModeEnabled = isFieldModeEnabled();
187     const bool& l_isLabModeEnabled =
188         !l_isFieldModeEnabled;                       // used for understanding
189     const bool& l_isPowerVsImage = vpdSpecificUtility::isPowerVsImage();
190     const bool& l_isNormalImage = !l_isPowerVsImage; // used for understanding
191 
192     if (!isValidImSeries(l_planarImValue))
193     {
194         // Create Errorlog for invalid IM series encountered
195         EventLogger::createSyncPel(
196             types::ErrorType::InvalidSystem, types::SeverityType::Error,
197             __FILE__, __FUNCTION__, 0,
198             std::string("Invalid IM found on the system planar, IM value : ") +
199                 l_planarImValue,
200             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
201 
202         return constants::SUCCESS;
203     }
204 
205     if (!l_eBmcImValue.empty())
206     {
207         if (isP10System(l_eBmcImValue))
208         {
209             if (isP10System(l_planarImValue))
210             {
211                 if (l_isFieldModeEnabled && l_isNormalImage)
212                 {
213                     EventLogger::createSyncPel(
214                         types::ErrorType::SystemTypeMismatch,
215                         types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
216                         std::string("Mismatch in IM value found eBMC IM [") +
217                             l_eBmcImValue + std::string("] planar IM [") +
218                             l_planarImValue +
219                             std::string("] Field mode enabled [") +
220                             ((l_isFieldModeEnabled) ? "true" : "false") +
221                             std::string("]"),
222                         std::nullopt, std::nullopt, std::nullopt, std::nullopt);
223 
224                     return constants::FAILURE;
225                 }
226             }
227             else if (isP11System(l_planarImValue))
228             {
229                 if (!(l_isLabModeEnabled && l_isNormalImage))
230                 {
231                     EventLogger::createSyncPel(
232                         types::ErrorType::SystemTypeMismatch,
233                         types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
234                         std::string("Mismatch in IM value found eBMC IM [") +
235                             l_eBmcImValue + std::string("] planar IM [") +
236                             l_planarImValue +
237                             std::string("] Field mode enabled [") +
238                             ((l_isFieldModeEnabled) ? "true" : "false") +
239                             std::string("]"),
240                         std::nullopt, std::nullopt, std::nullopt, std::nullopt);
241 
242                     return constants::FAILURE;
243                 }
244             }
245         }
246         else if (isP11System(l_eBmcImValue))
247         {
248             if (l_isPowerVsImage)
249             {
250                 EventLogger::createSyncPel(
251                     types::ErrorType::SystemTypeMismatch,
252                     types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
253                     std::string("Mismatch in IM value found eBMC IM [") +
254                         l_eBmcImValue + std::string("] planar IM [") +
255                         l_planarImValue +
256                         std::string("] Field mode enabled [") +
257                         ((l_isFieldModeEnabled) ? "true" : "false") +
258                         std::string("]"),
259                     std::nullopt, std::nullopt, std::nullopt, std::nullopt);
260 
261                 return constants::FAILURE;
262             }
263             else
264             {
265                 if (isP10System(l_planarImValue))
266                 {
267                     updateSystemImValueInVpdToP11Series(l_planarImValue);
268                 }
269             }
270         }
271     }
272     else
273     {
274         if (isP11System(l_planarImValue) && l_isPowerVsImage)
275         {
276             EventLogger::createSyncPel(
277                 types::ErrorType::SystemTypeMismatch,
278                 types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
279                 std::string("Mismatch in IM value found eBMC IM [") +
280                     l_eBmcImValue + std::string("] planar IM [") +
281                     l_planarImValue + std::string("] Field mode enabled [") +
282                     ((l_isFieldModeEnabled) ? "true" : "false") +
283                     std::string("]"),
284                 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
285 
286             return constants::FAILURE;
287         }
288         else if (isP10System(l_planarImValue) && l_isNormalImage)
289         {
290             if (l_isLabModeEnabled)
291             {
292                 EventLogger::createSyncPel(
293                     types::ErrorType::UnknownSystemSettings,
294                     types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
295                     std::string("Mismatch in IM value found eBMC IM [") +
296                         l_eBmcImValue + std::string("] planar IM [") +
297                         l_planarImValue +
298                         std::string("] Field mode enabled [") +
299                         ((l_isFieldModeEnabled) ? "true" : "false") +
300                         std::string("]"),
301                     std::nullopt, std::nullopt, std::nullopt, std::nullopt);
302             }
303             else
304             {
305                 updateSystemImValueInVpdToP11Series(l_planarImValue);
306             }
307         }
308     }
309     return constants::SUCCESS;
310 }
311 } // namespace vpd
312