blob: 0b7fdc42ba9e99cdc249970a98d8d4f714a54854 [file] [log] [blame]
AppaRao Pulic532f552019-07-05 15:23:50 +05301/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
AppaRao Pulic532f552019-07-05 15:23:50 +053017#include "pfr.hpp"
AppaRao Puli67d184c2020-05-29 00:48:33 +053018
AppaRao Pulic532f552019-07-05 15:23:50 +053019#include "file.hpp"
AppaRao Puli4b639a22019-10-01 18:12:59 +053020#include "spiDev.hpp"
AppaRao Pulic532f552019-07-05 15:23:50 +053021
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +000022#include <gpiod.hpp>
23
AppaRao Puli67d184c2020-05-29 00:48:33 +053024#include <iomanip>
25#include <iostream>
26#include <sstream>
27
AppaRao Pulic532f552019-07-05 15:23:50 +053028namespace pfr
29{
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000030
31using GetSubTreeType = std::vector<
32 std::pair<std::string,
33 std::vector<std::pair<std::string, std::vector<std::string>>>>>;
34
35static int i2cBusNumber = 4;
36static int i2cSlaveAddress = 56;
AppaRao Pulic532f552019-07-05 15:23:50 +053037
38// CPLD mailbox registers
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +000039static constexpr uint8_t pfrROTId = 0x00;
AppaRao Pulic532f552019-07-05 15:23:50 +053040static constexpr uint8_t cpldROTVersion = 0x01;
41static constexpr uint8_t cpldROTSvn = 0x02;
42static constexpr uint8_t platformState = 0x03;
43static constexpr uint8_t recoveryCount = 0x04;
44static constexpr uint8_t lastRecoveryReason = 0x05;
45static constexpr uint8_t panicEventCount = 0x06;
46static constexpr uint8_t panicEventReason = 0x07;
47static constexpr uint8_t majorErrorCode = 0x08;
48static constexpr uint8_t minorErrorCode = 0x09;
49static constexpr uint8_t provisioningStatus = 0x0A;
Vikram Bodireddy08841912020-08-31 18:11:45 +053050static constexpr uint8_t bmcBootCheckpointRev1 = 0x0F;
51static constexpr uint8_t bmcBootCheckpoint = 0x60;
AppaRao Pulia04c8252019-07-31 22:59:28 +053052static constexpr uint8_t pchActiveMajorVersion = 0x15;
53static constexpr uint8_t pchActiveMinorVersion = 0x16;
AppaRao Pulia04c8252019-07-31 22:59:28 +053054static constexpr uint8_t pchRecoveryMajorVersion = 0x1B;
55static constexpr uint8_t pchRecoveryMinorVersion = 0x1C;
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +000056static constexpr uint8_t CPLDHashRegStart = 0x20;
57static constexpr uint8_t pfrRoTValue = 0xDE;
Vikram Bodireddy8292dc62021-05-26 13:31:47 +053058static constexpr uint8_t afmActiveMajorVersion = 0x75;
59static constexpr uint8_t afmActiveMinorVersion = 0x76;
60static constexpr uint8_t afmRecoveryMajorVersion = 0x78;
61static constexpr uint8_t afmRecoveryMinorVersion = 0x79;
AppaRao Pulic532f552019-07-05 15:23:50 +053062
63static constexpr uint8_t ufmLockedMask = (0x1 << 0x04);
64static constexpr uint8_t ufmProvisionedMask = (0x1 << 0x05);
65
AppaRao Puli4b639a22019-10-01 18:12:59 +053066// PFR MTD devices
67static constexpr const char* bmcActiveImgPfmMTDDev = "/dev/mtd/pfm";
68static constexpr const char* bmcRecoveryImgMTDDev = "/dev/mtd/rc-image";
69
70// PFM offset in full image
71static constexpr const uint32_t pfmBaseOffsetInImage = 0x400;
72
73// OFFSET values in PFM
74static constexpr const uint32_t verOffsetInPFM = 0x406;
75static constexpr const uint32_t buildNumOffsetInPFM = 0x40C;
76static constexpr const uint32_t buildHashOffsetInPFM = 0x40D;
77
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +000078static const std::array<std::string, 8> mainCPLDGpioLines = {
79 "MAIN_PLD_MAJOR_REV_BIT3", "MAIN_PLD_MAJOR_REV_BIT2",
80 "MAIN_PLD_MAJOR_REV_BIT1", "MAIN_PLD_MAJOR_REV_BIT0",
81 "MAIN_PLD_MINOR_REV_BIT3", "MAIN_PLD_MINOR_REV_BIT2",
82 "MAIN_PLD_MINOR_REV_BIT1", "MAIN_PLD_MINOR_REV_BIT0"};
83
84static const std::array<std::string, 8> pldGpioLines = {
85 "SGPIO_PLD_MAJOR_REV_BIT3", "SGPIO_PLD_MAJOR_REV_BIT2",
86 "SGPIO_PLD_MAJOR_REV_BIT1", "SGPIO_PLD_MAJOR_REV_BIT0",
87 "SGPIO_PLD_MINOR_REV_BIT3", "SGPIO_PLD_MINOR_REV_BIT2",
88 "SGPIO_PLD_MINOR_REV_BIT1", "SGPIO_PLD_MINOR_REV_BIT0"};
89
Chalapathi Venkataramashetty00acaff2020-12-24 11:01:17 +000090bool exceptionFlag = true;
91
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000092void init(std::shared_ptr<sdbusplus::asio::connection> conn,
93 bool& i2cConfigLoaded)
94{
95 conn->async_method_call(
96 [conn, &i2cConfigLoaded](const boost::system::error_code ec,
97 const GetSubTreeType& resp) {
Patrick Williams304e82e2023-05-10 07:51:13 -050098 if (ec || resp.size() != 1)
99 {
100 return;
101 }
102 if (resp[0].second.begin() == resp[0].second.end())
103 return;
104 const std::string& objPath = resp[0].first;
105 const std::string& serviceName = resp[0].second.begin()->first;
Vikram Bodireddy1c06ae42021-07-08 15:26:51 +0530106
Patrick Williams304e82e2023-05-10 07:51:13 -0500107 const std::string match = "Baseboard/PFR";
108 if (boost::ends_with(objPath, match))
109 {
110 // PFR object found.. check for PFR support
111 conn->async_method_call(
112 [objPath, serviceName, conn, &i2cConfigLoaded](
113 boost::system::error_code ec,
114 const std::vector<std::pair<
115 std::string, std::variant<std::string, uint64_t>>>&
116 propertiesList) {
117 if (ec)
118 {
119 phosphor::logging::log<phosphor::logging::level::ERR>(
120 "Error to Get PFR properties.",
121 phosphor::logging::entry("MSG=%s",
122 ec.message().c_str()));
123 return;
124 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000125
Patrick Williams304e82e2023-05-10 07:51:13 -0500126 const uint64_t* i2cBus = nullptr;
127 const uint64_t* address = nullptr;
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000128
Patrick Williams304e82e2023-05-10 07:51:13 -0500129 for (const auto& [propName, propVariant] : propertiesList)
130 {
131 if (propName == "Address")
132 {
133 address = std::get_if<uint64_t>(&propVariant);
134 }
135 else if (propName == "Bus")
136 {
137 i2cBus = std::get_if<uint64_t>(&propVariant);
138 }
139 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000140
Patrick Williams304e82e2023-05-10 07:51:13 -0500141 if ((address == nullptr) || (i2cBus == nullptr))
142 {
143 phosphor::logging::log<phosphor::logging::level::ERR>(
144 "Unable to read the pfr properties");
145 return;
146 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000147
Patrick Williams304e82e2023-05-10 07:51:13 -0500148 i2cBusNumber = static_cast<int>(*i2cBus);
149 i2cSlaveAddress = static_cast<int>(*address);
150 i2cConfigLoaded = true;
151 },
152 serviceName, objPath, "org.freedesktop.DBus.Properties",
153 "GetAll", "xyz.openbmc_project.Configuration.PFR");
154 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000155 },
156 "xyz.openbmc_project.ObjectMapper",
157 "/xyz/openbmc_project/object_mapper",
158 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
159 "/xyz/openbmc_project/inventory/system", 0,
160 std::array<const char*, 1>{"xyz.openbmc_project.Configuration.PFR"});
161 return;
162}
163
AppaRao Pulidbe184d2019-10-09 18:04:22 +0530164std::string toHexString(const uint8_t val)
AppaRao Pulic532f552019-07-05 15:23:50 +0530165{
166 std::stringstream stream;
AppaRao Pulidbe184d2019-10-09 18:04:22 +0530167 stream << std::setfill('0') << std::setw(2) << std::hex
168 << static_cast<int>(val);
AppaRao Pulic532f552019-07-05 15:23:50 +0530169 return stream.str();
170}
171
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000172static std::string readCPLDHash()
173{
174 std::stringstream hashStrStream;
175 static constexpr uint8_t hashLength = 32;
176 std::array<uint8_t, hashLength> hashValue = {0};
177 try
178 {
179 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
180 if (cpldDev.i2cReadBlockData(CPLDHashRegStart, hashLength,
181 hashValue.data()))
182 {
183 for (const auto& i : hashValue)
184 {
185 hashStrStream << std::setfill('0') << std::setw(2) << std::hex
186 << static_cast<int>(i);
187 }
188 }
189 else
190 {
191 // read failed
192 phosphor::logging::log<phosphor::logging::level::ERR>(
193 "Failed to read CPLD Hash string");
194 return "";
195 }
196 }
197 catch (const std::exception& e)
198 {
199 phosphor::logging::log<phosphor::logging::level::ERR>(
200 "Exception caught in readCPLDHash.",
201 phosphor::logging::entry("MSG=%s", e.what()));
202 return "";
203 }
204 return hashStrStream.str();
205}
206
AppaRao Puli4b639a22019-10-01 18:12:59 +0530207static std::string readVersionFromCPLD(const uint8_t majorReg,
208 const uint8_t minorReg)
AppaRao Pulic532f552019-07-05 15:23:50 +0530209{
210 try
211 {
AppaRao Pulic532f552019-07-05 15:23:50 +0530212 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
213 uint8_t majorVer = cpldDev.i2cReadByteData(majorReg);
214 uint8_t minorVer = cpldDev.i2cReadByteData(minorReg);
AppaRao Puli90fb45c2020-01-21 16:50:53 +0530215 // Major and Minor versions should be binary encoded strings.
Patrick Williams304e82e2023-05-10 07:51:13 -0500216 std::string version = std::to_string(majorVer) + "." +
217 std::to_string(minorVer);
AppaRao Pulic532f552019-07-05 15:23:50 +0530218 return version;
219 }
220 catch (const std::exception& e)
221 {
222 phosphor::logging::log<phosphor::logging::level::ERR>(
AppaRao Puli4b639a22019-10-01 18:12:59 +0530223 "Exception caught in readVersionFromCPLD.",
AppaRao Pulic532f552019-07-05 15:23:50 +0530224 phosphor::logging::entry("MSG=%s", e.what()));
225 return "";
226 }
227}
228
AppaRao Puli4b639a22019-10-01 18:12:59 +0530229static std::string readBMCVersionFromSPI(const ImageType& imgType)
230{
231 std::string mtdDev;
232 uint32_t verOffset = verOffsetInPFM;
233 uint32_t bldNumOffset = buildNumOffsetInPFM;
234 uint32_t bldHashOffset = buildHashOffsetInPFM;
235
236 if (imgType == ImageType::bmcActive)
237 {
238 // For Active image, PFM is emulated as separate MTD device.
239 mtdDev = bmcActiveImgPfmMTDDev;
240 }
241 else if (imgType == ImageType::bmcRecovery)
242 {
243 // For Recovery image, PFM is part of compressed Image
244 // at offset 0x400.
245 mtdDev = bmcRecoveryImgMTDDev;
246 verOffset += pfmBaseOffsetInImage;
247 bldNumOffset += pfmBaseOffsetInImage;
248 bldHashOffset += pfmBaseOffsetInImage;
249 }
250 else
251 {
252 phosphor::logging::log<phosphor::logging::level::ERR>(
253 "Invalid image type passed to readBMCVersionFromSPI.");
254 return "";
255 }
256
257 uint8_t buildNo = 0;
258 std::array<uint8_t, 2> ver;
259 std::array<uint8_t, 3> buildHash;
260
261 try
262 {
263 SPIDev spiDev(mtdDev);
264 spiDev.spiReadData(verOffset, ver.size(),
265 reinterpret_cast<void*>(ver.data()));
266 spiDev.spiReadData(bldNumOffset, sizeof(buildNo),
267 reinterpret_cast<void*>(&buildNo));
268 spiDev.spiReadData(bldHashOffset, buildHash.size(),
269 reinterpret_cast<void*>(buildHash.data()));
270 }
271 catch (const std::exception& e)
272 {
273 phosphor::logging::log<phosphor::logging::level::ERR>(
274 "Exception caught in readBMCVersionFromSPI.",
275 phosphor::logging::entry("MSG=%s", e.what()));
276 return "";
277 }
AppaRao Puli90fb45c2020-01-21 16:50:53 +0530278
279 // Version format: <major>.<minor>-<build bum>-g<build hash>
280 // Example: 0.11-7-g1e5c2d
281 // Major, minor and build numberare BCD encoded.
282 std::string version =
283 std::to_string(ver[0]) + "." + std::to_string(ver[1]) + "-" +
284 std::to_string(buildNo) + "-g" + toHexString(buildHash[0]) +
285 toHexString(buildHash[1]) + toHexString(buildHash[2]);
AppaRao Puli4b639a22019-10-01 18:12:59 +0530286 return version;
287}
288
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000289static bool getGPIOInput(const std::string& name, gpiod::line& gpioLine,
290 uint8_t* value)
291{
292 // Find the GPIO line
293 gpioLine = gpiod::find_line(name);
294 if (!gpioLine)
295 {
296 phosphor::logging::log<phosphor::logging::level::ERR>(
297 "Failed to find the GPIO line: ",
298 phosphor::logging::entry("MSG=%s", name.c_str()));
299 return false;
300 }
301 try
302 {
303 gpioLine.request({__FUNCTION__, gpiod::line_request::DIRECTION_INPUT});
304 }
Patrick Williams4990c9e2021-10-06 14:40:02 -0500305 catch (const std::exception& e)
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000306 {
307 phosphor::logging::log<phosphor::logging::level::ERR>(
308 "Failed to request the GPIO line",
309 phosphor::logging::entry("MSG=%s", e.what()));
310 gpioLine.release();
311 return false;
312 }
313 try
314 {
315 *value = gpioLine.get_value();
316 }
Patrick Williams4990c9e2021-10-06 14:40:02 -0500317 catch (const std::exception& e)
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000318 {
319 phosphor::logging::log<phosphor::logging::level::ERR>(
320 "Failed to get the value of GPIO line",
321 phosphor::logging::entry("MSG=%s", e.what()));
322 gpioLine.release();
323 return false;
324 }
325 gpioLine.release();
326 return true;
327}
328
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000329std::string readCPLDVersion()
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000330{
331 // CPLD SGPIO lines
332 gpiod::line mainCPLDLine;
333 gpiod::line pldLine;
334 // read main pld and pld version
335 uint8_t mainCPLDVer = 0;
336 uint8_t pldVer = 0;
337 // main CPLD
338 for (const auto& gLine : mainCPLDGpioLines)
339 {
340 uint8_t value = 0;
341 if (getGPIOInput(gLine, mainCPLDLine, &value))
342 {
343 mainCPLDVer <<= 1;
344 mainCPLDVer = mainCPLDVer | value;
345 }
346 else
347 {
348 phosphor::logging::log<phosphor::logging::level::ERR>(
349 "Failed to read GPIO line: ",
350 phosphor::logging::entry("MSG=%s", gLine.c_str()));
351 mainCPLDVer = 0;
352 break;
353 }
354 }
355
356 // pld lines
357 for (const auto& gLine : pldGpioLines)
358 {
359 uint8_t value = 0;
360 if (getGPIOInput(gLine, pldLine, &value))
361 {
362 pldVer <<= 1;
363 pldVer = pldVer | value;
364 }
365 else
366 {
367 phosphor::logging::log<phosphor::logging::level::ERR>(
368 "Failed to read GPIO line: ",
369 phosphor::logging::entry("MSG=%s", gLine.c_str()));
370 pldVer = 0;
371 break;
372 }
373 }
374
375 std::string svnRoTHash = "";
376
377 // check if reg 0x00 read 0xde
378 uint8_t cpldRoTValue = 0;
Zhikui Renace48a72020-08-12 15:54:42 -0700379 try
380 {
381 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
382 cpldRoTValue = cpldDev.i2cReadByteData(pfrROTId);
383 }
384 catch (const std::exception& e)
385 {
386 phosphor::logging::log<phosphor::logging::level::ERR>(
387 "Exception caught in readCPLDVersion.",
388 phosphor::logging::entry("MSG=%s", e.what()));
389 }
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000390
391 if (cpldRoTValue == pfrRoTValue)
392 {
393 // read SVN and RoT version
394 std::string svnRoTver = readVersionFromCPLD(cpldROTVersion, cpldROTSvn);
395
396 // read CPLD hash
397 std::string cpldHash = readCPLDHash();
398 svnRoTHash = "-" + svnRoTver + "-" + cpldHash;
399 }
400 else
401 {
402 phosphor::logging::log<phosphor::logging::level::INFO>(
403 "PFR-CPLD not present.");
404 }
405
406 // CPLD version format:
407 // When PFR CPLD is present
408 // <MainPLDMajorMinor.PLDMajorMinor>-<SVN.RoT>-<CPLD-Hash>
409 // Example: 2.7-1.1-<Hash string>
410
411 // When Non-PFR CPLD is present -> <MainPLDMajorMinor.PLDMajorMinor>
412 // Example: 2.7
413
Patrick Williams304e82e2023-05-10 07:51:13 -0500414 std::string version = std::to_string(mainCPLDVer) + "." +
415 std::to_string(pldVer) + svnRoTHash;
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000416 return version;
417}
418
AppaRao Puli4b639a22019-10-01 18:12:59 +0530419std::string getFirmwareVersion(const ImageType& imgType)
420{
421 switch (imgType)
422 {
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +0530423 case (ImageType::cpldActive):
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000424 {
425 return readCPLDVersion();
426 }
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +0530427 case (ImageType::cpldRecovery):
AppaRao Puli4b639a22019-10-01 18:12:59 +0530428 {
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +0530429 // TO-DO: Need to update once CPLD supported Firmware is available
AppaRao Puli4b639a22019-10-01 18:12:59 +0530430 return readVersionFromCPLD(cpldROTVersion, cpldROTSvn);
431 }
432 case (ImageType::biosActive):
433 {
434 return readVersionFromCPLD(pchActiveMajorVersion,
435 pchActiveMinorVersion);
436 }
437 case (ImageType::biosRecovery):
438 {
439 return readVersionFromCPLD(pchRecoveryMajorVersion,
440 pchRecoveryMinorVersion);
441 }
442 case (ImageType::bmcActive):
443 case (ImageType::bmcRecovery):
444 {
445 return readBMCVersionFromSPI(imgType);
446 }
Vikram Bodireddy8292dc62021-05-26 13:31:47 +0530447 case (ImageType::afmActive):
448 {
449 return readVersionFromCPLD(afmActiveMajorVersion,
450 afmActiveMinorVersion);
451 }
452 case (ImageType::afmRecovery):
453 {
454 return readVersionFromCPLD(afmRecoveryMajorVersion,
455 afmRecoveryMinorVersion);
456 }
AppaRao Puli4b639a22019-10-01 18:12:59 +0530457 default:
458 // Invalid image Type.
459 return "";
460 }
461}
462
Chalapathi Venkataramashettyf8819702021-02-03 09:43:46 +0000463int getProvisioningStatus(bool& ufmLocked, bool& ufmProvisioned,
464 bool& ufmSupport)
AppaRao Pulic532f552019-07-05 15:23:50 +0530465{
466 try
467 {
468 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
469 uint8_t provStatus = cpldDev.i2cReadByteData(provisioningStatus);
Chalapathi Venkataramashettyf8819702021-02-03 09:43:46 +0000470 uint8_t pfrRoT = cpldDev.i2cReadByteData(pfrROTId);
AppaRao Pulic532f552019-07-05 15:23:50 +0530471 ufmLocked = (provStatus & ufmLockedMask);
472 ufmProvisioned = (provStatus & ufmProvisionedMask);
Chalapathi Venkataramashettyf8819702021-02-03 09:43:46 +0000473 ufmSupport = (pfrRoT & pfrRoTValue);
AppaRao Pulic532f552019-07-05 15:23:50 +0530474 return 0;
475 }
476 catch (const std::exception& e)
477 {
478 phosphor::logging::log<phosphor::logging::level::ERR>(
479 "Exception caught in getProvisioningStatus.",
480 phosphor::logging::entry("MSG=%s", e.what()));
481 return -1;
482 }
483}
484
Zhikui Renc96f37d2021-12-08 15:40:51 -0800485int getPlatformState(uint8_t& state)
486{
487 try
488 {
489 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
490 state = cpldDev.i2cReadByteData(platformState);
491
492 return 0;
493 }
494 catch (const std::exception& e)
495 {
496 phosphor::logging::log<phosphor::logging::level::ERR>(
497 "Exception caught in getPlatformState.",
498 phosphor::logging::entry("MSG=%s", e.what()));
499 return -1;
500 }
501}
502
AppaRao Pulidbe184d2019-10-09 18:04:22 +0530503int readCpldReg(const ActionType& action, uint8_t& value)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530504{
505 uint8_t cpldReg;
506
507 switch (action)
508 {
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000509 case (ActionType::readRoTRev):
510 cpldReg = cpldROTVersion;
511 break;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530512 case (ActionType::recoveryCount):
513 cpldReg = recoveryCount;
514 break;
515 case (ActionType::recoveryReason):
516 cpldReg = lastRecoveryReason;
517 break;
518 case (ActionType::panicCount):
519 cpldReg = panicEventCount;
520 break;
521 case (ActionType::panicReason):
522 cpldReg = panicEventReason;
523 break;
524 case (ActionType::majorError):
525 cpldReg = majorErrorCode;
526 break;
527 case (ActionType::minorError):
528 cpldReg = minorErrorCode;
529 break;
530
531 default:
532 phosphor::logging::log<phosphor::logging::level::ERR>(
533 "Invalid CPLD read action.");
534 return -1;
535 }
536
537 try
538 {
539 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
540 value = cpldDev.i2cReadByteData(cpldReg);
541 return 0;
542 }
543 catch (const std::exception& e)
544 {
Chalapathi Venkataramashetty00acaff2020-12-24 11:01:17 +0000545 if (exceptionFlag)
546 {
547 exceptionFlag = false;
548 phosphor::logging::log<phosphor::logging::level::ERR>(
549 "Exception caught in readCpldReg.",
550 phosphor::logging::entry("MSG=%s", e.what()));
551 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530552 return -1;
553 }
554}
555
AppaRao Puli46cead92019-07-22 16:50:09 +0530556int setBMCBootCheckpoint(const uint8_t checkPoint)
557{
Vikram Bodireddy08841912020-08-31 18:11:45 +0530558 uint8_t bmcBootCheckpointReg = bmcBootCheckpoint;
559
560 // check if reg 0x01(RoTRev) is 1 or 2.
561 // checkpoint register changes for RoT Rev 1 and 2
562 uint8_t cpldRoTRev = 0;
AppaRao Puli46cead92019-07-22 16:50:09 +0530563 try
564 {
565 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
Vikram Bodireddy08841912020-08-31 18:11:45 +0530566 cpldRoTRev = cpldDev.i2cReadByteData(cpldROTVersion);
567 }
568 catch (const std::exception& e)
569 {
570 phosphor::logging::log<phosphor::logging::level::ERR>(
571 "Exception caught in reading RoT rev.",
572 phosphor::logging::entry("MSG=%s", e.what()));
573 return -1;
574 }
575
576 // latest PFR has different check point register
577 if (cpldRoTRev <= 1)
578 {
579 bmcBootCheckpointReg = bmcBootCheckpointRev1;
580 }
581
582 try
583 {
584 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
585 cpldDev.i2cWriteByteData(bmcBootCheckpointReg, checkPoint);
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530586 phosphor::logging::log<phosphor::logging::level::INFO>(
587 "Successfully set the PFR CPLD checkpoint 9.");
AppaRao Puli46cead92019-07-22 16:50:09 +0530588 return 0;
589 }
590 catch (const std::exception& e)
591 {
592 phosphor::logging::log<phosphor::logging::level::ERR>(
593 "Exception caught in setBMCBootCheckout.",
594 phosphor::logging::entry("MSG=%s", e.what()));
595 return -1;
596 }
597}
598
deepak kumar agrawalb29a15c2022-03-25 07:45:57 +0000599static bool setMBRegister(uint32_t regOffset, uint8_t regValue)
600{
601 try
602 {
603 I2CFile mailDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
604 mailDev.i2cWriteByteData(regOffset, regValue);
605 return true;
606 }
607 catch (const std::exception& e)
608 {
609 phosphor::logging::log<phosphor::logging::level::ERR>(
610 "Exception caught in setting PFR Mailbox.",
611 phosphor::logging::entry("MSG=%s", e.what()));
612 return false;
613 }
614}
615
616int setBMCBusy(bool setValue)
617{
618 uint32_t bmcBusyReg = 0x63;
619 uint8_t valHigh = 0x01;
620 uint8_t mailBoxReply = 0;
621
622 if (getMBRegister(bmcBusyReg, mailBoxReply))
623 {
624 return -1;
625 }
626 uint8_t readValue = mailBoxReply | valHigh;
627 if (setValue == false)
628 {
629 readValue &= 0b11111110;
630 }
631 if (!setMBRegister(bmcBusyReg, readValue))
632 {
633 return -1;
634 }
635 if (setValue == false)
636 {
637 phosphor::logging::log<phosphor::logging::level::DEBUG>(
638 "Successfully reset the PFR MailBox register.");
639 }
640 else
641 {
642 phosphor::logging::log<phosphor::logging::level::DEBUG>(
643 "Successfully set the PFR MailBox to BMCBusy.");
644 }
645 return 0;
646}
647
648int getMBRegister(uint32_t regAddr, uint8_t& mailBoxReply)
649{
650 // Read from PFR CPLD's mailbox register
651 try
652 {
653 I2CFile mailReadDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
654
655 mailBoxReply = mailReadDev.i2cReadByteData(regAddr);
656 }
657 catch (const std::exception& e)
658 {
659 phosphor::logging::log<phosphor::logging::level::ERR>(
660 "Exception caught in mailbox reading.",
661 phosphor::logging::entry("MSG=%s", e.what()));
662 throw;
663 }
664 return 0;
665}
666
AppaRao Pulic532f552019-07-05 15:23:50 +0530667} // namespace pfr