blob: 61c52f086572796bfcedf3e29a0118f1e50f4376 [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
Chalapathi Venkataramashetty00acaff2020-12-24 11:01:17 +000084bool exceptionFlag = true;
85
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000086void init(std::shared_ptr<sdbusplus::asio::connection> conn,
87 bool& i2cConfigLoaded)
88{
89 conn->async_method_call(
90 [conn, &i2cConfigLoaded](const boost::system::error_code ec,
91 const GetSubTreeType& resp) {
Patrick Williams304e82e2023-05-10 07:51:13 -050092 if (ec || resp.size() != 1)
93 {
94 return;
95 }
96 if (resp[0].second.begin() == resp[0].second.end())
97 return;
98 const std::string& objPath = resp[0].first;
99 const std::string& serviceName = resp[0].second.begin()->first;
Vikram Bodireddy1c06ae42021-07-08 15:26:51 +0530100
Patrick Williams304e82e2023-05-10 07:51:13 -0500101 const std::string match = "Baseboard/PFR";
102 if (boost::ends_with(objPath, match))
103 {
104 // PFR object found.. check for PFR support
105 conn->async_method_call(
106 [objPath, serviceName, conn, &i2cConfigLoaded](
107 boost::system::error_code ec,
108 const std::vector<std::pair<
109 std::string, std::variant<std::string, uint64_t>>>&
110 propertiesList) {
111 if (ec)
112 {
113 phosphor::logging::log<phosphor::logging::level::ERR>(
114 "Error to Get PFR properties.",
115 phosphor::logging::entry("MSG=%s",
116 ec.message().c_str()));
117 return;
118 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000119
Patrick Williams304e82e2023-05-10 07:51:13 -0500120 const uint64_t* i2cBus = nullptr;
121 const uint64_t* address = nullptr;
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000122
Patrick Williams304e82e2023-05-10 07:51:13 -0500123 for (const auto& [propName, propVariant] : propertiesList)
124 {
125 if (propName == "Address")
126 {
127 address = std::get_if<uint64_t>(&propVariant);
128 }
129 else if (propName == "Bus")
130 {
131 i2cBus = std::get_if<uint64_t>(&propVariant);
132 }
133 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000134
Patrick Williams304e82e2023-05-10 07:51:13 -0500135 if ((address == nullptr) || (i2cBus == nullptr))
136 {
137 phosphor::logging::log<phosphor::logging::level::ERR>(
138 "Unable to read the pfr properties");
139 return;
140 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000141
Patrick Williams304e82e2023-05-10 07:51:13 -0500142 i2cBusNumber = static_cast<int>(*i2cBus);
143 i2cSlaveAddress = static_cast<int>(*address);
144 i2cConfigLoaded = true;
145 },
146 serviceName, objPath, "org.freedesktop.DBus.Properties",
147 "GetAll", "xyz.openbmc_project.Configuration.PFR");
148 }
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000149 },
150 "xyz.openbmc_project.ObjectMapper",
151 "/xyz/openbmc_project/object_mapper",
152 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
153 "/xyz/openbmc_project/inventory/system", 0,
154 std::array<const char*, 1>{"xyz.openbmc_project.Configuration.PFR"});
155 return;
156}
157
AppaRao Pulidbe184d2019-10-09 18:04:22 +0530158std::string toHexString(const uint8_t val)
AppaRao Pulic532f552019-07-05 15:23:50 +0530159{
160 std::stringstream stream;
AppaRao Pulidbe184d2019-10-09 18:04:22 +0530161 stream << std::setfill('0') << std::setw(2) << std::hex
162 << static_cast<int>(val);
AppaRao Pulic532f552019-07-05 15:23:50 +0530163 return stream.str();
164}
165
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000166static std::string readCPLDHash()
167{
168 std::stringstream hashStrStream;
169 static constexpr uint8_t hashLength = 32;
170 std::array<uint8_t, hashLength> hashValue = {0};
171 try
172 {
173 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
174 if (cpldDev.i2cReadBlockData(CPLDHashRegStart, hashLength,
175 hashValue.data()))
176 {
177 for (const auto& i : hashValue)
178 {
179 hashStrStream << std::setfill('0') << std::setw(2) << std::hex
180 << static_cast<int>(i);
181 }
182 }
183 else
184 {
185 // read failed
186 phosphor::logging::log<phosphor::logging::level::ERR>(
187 "Failed to read CPLD Hash string");
188 return "";
189 }
190 }
191 catch (const std::exception& e)
192 {
193 phosphor::logging::log<phosphor::logging::level::ERR>(
194 "Exception caught in readCPLDHash.",
195 phosphor::logging::entry("MSG=%s", e.what()));
196 return "";
197 }
198 return hashStrStream.str();
199}
200
AppaRao Puli4b639a22019-10-01 18:12:59 +0530201static std::string readVersionFromCPLD(const uint8_t majorReg,
202 const uint8_t minorReg)
AppaRao Pulic532f552019-07-05 15:23:50 +0530203{
204 try
205 {
AppaRao Pulic532f552019-07-05 15:23:50 +0530206 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
207 uint8_t majorVer = cpldDev.i2cReadByteData(majorReg);
208 uint8_t minorVer = cpldDev.i2cReadByteData(minorReg);
AppaRao Puli90fb45c2020-01-21 16:50:53 +0530209 // Major and Minor versions should be binary encoded strings.
Patrick Williams304e82e2023-05-10 07:51:13 -0500210 std::string version = std::to_string(majorVer) + "." +
211 std::to_string(minorVer);
AppaRao Pulic532f552019-07-05 15:23:50 +0530212 return version;
213 }
214 catch (const std::exception& e)
215 {
216 phosphor::logging::log<phosphor::logging::level::ERR>(
AppaRao Puli4b639a22019-10-01 18:12:59 +0530217 "Exception caught in readVersionFromCPLD.",
AppaRao Pulic532f552019-07-05 15:23:50 +0530218 phosphor::logging::entry("MSG=%s", e.what()));
219 return "";
220 }
221}
222
AppaRao Puli4b639a22019-10-01 18:12:59 +0530223static std::string readBMCVersionFromSPI(const ImageType& imgType)
224{
225 std::string mtdDev;
226 uint32_t verOffset = verOffsetInPFM;
227 uint32_t bldNumOffset = buildNumOffsetInPFM;
228 uint32_t bldHashOffset = buildHashOffsetInPFM;
229
230 if (imgType == ImageType::bmcActive)
231 {
232 // For Active image, PFM is emulated as separate MTD device.
233 mtdDev = bmcActiveImgPfmMTDDev;
234 }
235 else if (imgType == ImageType::bmcRecovery)
236 {
237 // For Recovery image, PFM is part of compressed Image
238 // at offset 0x400.
239 mtdDev = bmcRecoveryImgMTDDev;
240 verOffset += pfmBaseOffsetInImage;
241 bldNumOffset += pfmBaseOffsetInImage;
242 bldHashOffset += pfmBaseOffsetInImage;
243 }
244 else
245 {
246 phosphor::logging::log<phosphor::logging::level::ERR>(
247 "Invalid image type passed to readBMCVersionFromSPI.");
248 return "";
249 }
250
251 uint8_t buildNo = 0;
252 std::array<uint8_t, 2> ver;
253 std::array<uint8_t, 3> buildHash;
254
255 try
256 {
257 SPIDev spiDev(mtdDev);
258 spiDev.spiReadData(verOffset, ver.size(),
259 reinterpret_cast<void*>(ver.data()));
260 spiDev.spiReadData(bldNumOffset, sizeof(buildNo),
261 reinterpret_cast<void*>(&buildNo));
262 spiDev.spiReadData(bldHashOffset, buildHash.size(),
263 reinterpret_cast<void*>(buildHash.data()));
264 }
265 catch (const std::exception& e)
266 {
267 phosphor::logging::log<phosphor::logging::level::ERR>(
268 "Exception caught in readBMCVersionFromSPI.",
269 phosphor::logging::entry("MSG=%s", e.what()));
270 return "";
271 }
AppaRao Puli90fb45c2020-01-21 16:50:53 +0530272
273 // Version format: <major>.<minor>-<build bum>-g<build hash>
274 // Example: 0.11-7-g1e5c2d
275 // Major, minor and build numberare BCD encoded.
276 std::string version =
277 std::to_string(ver[0]) + "." + std::to_string(ver[1]) + "-" +
278 std::to_string(buildNo) + "-g" + toHexString(buildHash[0]) +
279 toHexString(buildHash[1]) + toHexString(buildHash[2]);
AppaRao Puli4b639a22019-10-01 18:12:59 +0530280 return version;
281}
282
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000283static bool getGPIOInput(const std::string& name, gpiod::line& gpioLine,
284 uint8_t* value)
285{
286 // Find the GPIO line
287 gpioLine = gpiod::find_line(name);
288 if (!gpioLine)
289 {
290 phosphor::logging::log<phosphor::logging::level::ERR>(
291 "Failed to find the GPIO line: ",
292 phosphor::logging::entry("MSG=%s", name.c_str()));
293 return false;
294 }
295 try
296 {
297 gpioLine.request({__FUNCTION__, gpiod::line_request::DIRECTION_INPUT});
298 }
Patrick Williams4990c9e2021-10-06 14:40:02 -0500299 catch (const std::exception& e)
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000300 {
301 phosphor::logging::log<phosphor::logging::level::ERR>(
302 "Failed to request the GPIO line",
303 phosphor::logging::entry("MSG=%s", e.what()));
304 gpioLine.release();
305 return false;
306 }
307 try
308 {
309 *value = gpioLine.get_value();
310 }
Patrick Williams4990c9e2021-10-06 14:40:02 -0500311 catch (const std::exception& e)
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000312 {
313 phosphor::logging::log<phosphor::logging::level::ERR>(
314 "Failed to get the value of GPIO line",
315 phosphor::logging::entry("MSG=%s", e.what()));
316 gpioLine.release();
317 return false;
318 }
319 gpioLine.release();
320 return true;
321}
322
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000323std::string readCPLDVersion()
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000324{
325 // CPLD SGPIO lines
326 gpiod::line mainCPLDLine;
ankita prasad1218aa62023-07-26 05:25:51 +0000327 // read main pld version
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000328 uint8_t mainCPLDVer = 0;
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000329 // main CPLD
330 for (const auto& gLine : mainCPLDGpioLines)
331 {
332 uint8_t value = 0;
333 if (getGPIOInput(gLine, mainCPLDLine, &value))
334 {
335 mainCPLDVer <<= 1;
336 mainCPLDVer = mainCPLDVer | value;
337 }
338 else
339 {
340 phosphor::logging::log<phosphor::logging::level::ERR>(
341 "Failed to read GPIO line: ",
342 phosphor::logging::entry("MSG=%s", gLine.c_str()));
343 mainCPLDVer = 0;
344 break;
345 }
346 }
347
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000348 std::string svnRoTHash = "";
349
350 // check if reg 0x00 read 0xde
351 uint8_t cpldRoTValue = 0;
Zhikui Renace48a72020-08-12 15:54:42 -0700352 try
353 {
354 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
355 cpldRoTValue = cpldDev.i2cReadByteData(pfrROTId);
356 }
357 catch (const std::exception& e)
358 {
359 phosphor::logging::log<phosphor::logging::level::ERR>(
360 "Exception caught in readCPLDVersion.",
361 phosphor::logging::entry("MSG=%s", e.what()));
362 }
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000363
364 if (cpldRoTValue == pfrRoTValue)
365 {
366 // read SVN and RoT version
367 std::string svnRoTver = readVersionFromCPLD(cpldROTVersion, cpldROTSvn);
368
369 // read CPLD hash
370 std::string cpldHash = readCPLDHash();
371 svnRoTHash = "-" + svnRoTver + "-" + cpldHash;
372 }
373 else
374 {
375 phosphor::logging::log<phosphor::logging::level::INFO>(
376 "PFR-CPLD not present.");
377 }
378
379 // CPLD version format:
380 // When PFR CPLD is present
ankita prasad1218aa62023-07-26 05:25:51 +0000381 // <MainPLDMajorMinor>-<SVN.RoT>-<CPLD-Hash>
382 // Example: 2-1.1-<Hash string>
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000383
ankita prasad1218aa62023-07-26 05:25:51 +0000384 // When Non-PFR CPLD is present -> <MainPLDMajorMinor>
385 // Example: 2
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000386
ankita prasad1218aa62023-07-26 05:25:51 +0000387 std::string version = std::to_string(mainCPLDVer) + svnRoTHash;
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000388 return version;
389}
390
AppaRao Puli4b639a22019-10-01 18:12:59 +0530391std::string getFirmwareVersion(const ImageType& imgType)
392{
393 switch (imgType)
394 {
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +0530395 case (ImageType::cpldActive):
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +0000396 {
397 return readCPLDVersion();
398 }
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +0530399 case (ImageType::cpldRecovery):
AppaRao Puli4b639a22019-10-01 18:12:59 +0530400 {
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +0530401 // TO-DO: Need to update once CPLD supported Firmware is available
AppaRao Puli4b639a22019-10-01 18:12:59 +0530402 return readVersionFromCPLD(cpldROTVersion, cpldROTSvn);
403 }
404 case (ImageType::biosActive):
405 {
406 return readVersionFromCPLD(pchActiveMajorVersion,
407 pchActiveMinorVersion);
408 }
409 case (ImageType::biosRecovery):
410 {
411 return readVersionFromCPLD(pchRecoveryMajorVersion,
412 pchRecoveryMinorVersion);
413 }
414 case (ImageType::bmcActive):
415 case (ImageType::bmcRecovery):
416 {
417 return readBMCVersionFromSPI(imgType);
418 }
Vikram Bodireddy8292dc62021-05-26 13:31:47 +0530419 case (ImageType::afmActive):
420 {
421 return readVersionFromCPLD(afmActiveMajorVersion,
422 afmActiveMinorVersion);
423 }
424 case (ImageType::afmRecovery):
425 {
426 return readVersionFromCPLD(afmRecoveryMajorVersion,
427 afmRecoveryMinorVersion);
428 }
AppaRao Puli4b639a22019-10-01 18:12:59 +0530429 default:
430 // Invalid image Type.
431 return "";
432 }
433}
434
Chalapathi Venkataramashettyf8819702021-02-03 09:43:46 +0000435int getProvisioningStatus(bool& ufmLocked, bool& ufmProvisioned,
436 bool& ufmSupport)
AppaRao Pulic532f552019-07-05 15:23:50 +0530437{
438 try
439 {
440 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
441 uint8_t provStatus = cpldDev.i2cReadByteData(provisioningStatus);
Chalapathi Venkataramashettyf8819702021-02-03 09:43:46 +0000442 uint8_t pfrRoT = cpldDev.i2cReadByteData(pfrROTId);
AppaRao Pulic532f552019-07-05 15:23:50 +0530443 ufmLocked = (provStatus & ufmLockedMask);
444 ufmProvisioned = (provStatus & ufmProvisionedMask);
Chalapathi Venkataramashettyf8819702021-02-03 09:43:46 +0000445 ufmSupport = (pfrRoT & pfrRoTValue);
AppaRao Pulic532f552019-07-05 15:23:50 +0530446 return 0;
447 }
448 catch (const std::exception& e)
449 {
450 phosphor::logging::log<phosphor::logging::level::ERR>(
451 "Exception caught in getProvisioningStatus.",
452 phosphor::logging::entry("MSG=%s", e.what()));
453 return -1;
454 }
455}
456
Zhikui Renc96f37d2021-12-08 15:40:51 -0800457int getPlatformState(uint8_t& state)
458{
459 try
460 {
461 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
462 state = cpldDev.i2cReadByteData(platformState);
463
464 return 0;
465 }
466 catch (const std::exception& e)
467 {
468 phosphor::logging::log<phosphor::logging::level::ERR>(
469 "Exception caught in getPlatformState.",
470 phosphor::logging::entry("MSG=%s", e.what()));
471 return -1;
472 }
473}
474
AppaRao Pulidbe184d2019-10-09 18:04:22 +0530475int readCpldReg(const ActionType& action, uint8_t& value)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530476{
477 uint8_t cpldReg;
478
479 switch (action)
480 {
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000481 case (ActionType::readRoTRev):
482 cpldReg = cpldROTVersion;
483 break;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530484 case (ActionType::recoveryCount):
485 cpldReg = recoveryCount;
486 break;
487 case (ActionType::recoveryReason):
488 cpldReg = lastRecoveryReason;
489 break;
490 case (ActionType::panicCount):
491 cpldReg = panicEventCount;
492 break;
493 case (ActionType::panicReason):
494 cpldReg = panicEventReason;
495 break;
496 case (ActionType::majorError):
497 cpldReg = majorErrorCode;
498 break;
499 case (ActionType::minorError):
500 cpldReg = minorErrorCode;
501 break;
502
503 default:
504 phosphor::logging::log<phosphor::logging::level::ERR>(
505 "Invalid CPLD read action.");
506 return -1;
507 }
508
509 try
510 {
511 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
512 value = cpldDev.i2cReadByteData(cpldReg);
513 return 0;
514 }
515 catch (const std::exception& e)
516 {
Chalapathi Venkataramashetty00acaff2020-12-24 11:01:17 +0000517 if (exceptionFlag)
518 {
519 exceptionFlag = false;
520 phosphor::logging::log<phosphor::logging::level::ERR>(
521 "Exception caught in readCpldReg.",
522 phosphor::logging::entry("MSG=%s", e.what()));
523 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530524 return -1;
525 }
526}
527
AppaRao Puli46cead92019-07-22 16:50:09 +0530528int setBMCBootCheckpoint(const uint8_t checkPoint)
529{
Vikram Bodireddy08841912020-08-31 18:11:45 +0530530 uint8_t bmcBootCheckpointReg = bmcBootCheckpoint;
531
532 // check if reg 0x01(RoTRev) is 1 or 2.
533 // checkpoint register changes for RoT Rev 1 and 2
534 uint8_t cpldRoTRev = 0;
AppaRao Puli46cead92019-07-22 16:50:09 +0530535 try
536 {
537 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
Vikram Bodireddy08841912020-08-31 18:11:45 +0530538 cpldRoTRev = cpldDev.i2cReadByteData(cpldROTVersion);
539 }
540 catch (const std::exception& e)
541 {
542 phosphor::logging::log<phosphor::logging::level::ERR>(
543 "Exception caught in reading RoT rev.",
544 phosphor::logging::entry("MSG=%s", e.what()));
545 return -1;
546 }
547
548 // latest PFR has different check point register
549 if (cpldRoTRev <= 1)
550 {
551 bmcBootCheckpointReg = bmcBootCheckpointRev1;
552 }
553
554 try
555 {
556 I2CFile cpldDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
557 cpldDev.i2cWriteByteData(bmcBootCheckpointReg, checkPoint);
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530558 phosphor::logging::log<phosphor::logging::level::INFO>(
559 "Successfully set the PFR CPLD checkpoint 9.");
AppaRao Puli46cead92019-07-22 16:50:09 +0530560 return 0;
561 }
562 catch (const std::exception& e)
563 {
564 phosphor::logging::log<phosphor::logging::level::ERR>(
565 "Exception caught in setBMCBootCheckout.",
566 phosphor::logging::entry("MSG=%s", e.what()));
567 return -1;
568 }
569}
570
deepak kumar agrawalb29a15c2022-03-25 07:45:57 +0000571static bool setMBRegister(uint32_t regOffset, uint8_t regValue)
572{
573 try
574 {
575 I2CFile mailDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
576 mailDev.i2cWriteByteData(regOffset, regValue);
577 return true;
578 }
579 catch (const std::exception& e)
580 {
581 phosphor::logging::log<phosphor::logging::level::ERR>(
582 "Exception caught in setting PFR Mailbox.",
583 phosphor::logging::entry("MSG=%s", e.what()));
584 return false;
585 }
586}
587
588int setBMCBusy(bool setValue)
589{
590 uint32_t bmcBusyReg = 0x63;
591 uint8_t valHigh = 0x01;
592 uint8_t mailBoxReply = 0;
593
594 if (getMBRegister(bmcBusyReg, mailBoxReply))
595 {
596 return -1;
597 }
598 uint8_t readValue = mailBoxReply | valHigh;
599 if (setValue == false)
600 {
601 readValue &= 0b11111110;
602 }
603 if (!setMBRegister(bmcBusyReg, readValue))
604 {
605 return -1;
606 }
607 if (setValue == false)
608 {
609 phosphor::logging::log<phosphor::logging::level::DEBUG>(
610 "Successfully reset the PFR MailBox register.");
611 }
612 else
613 {
614 phosphor::logging::log<phosphor::logging::level::DEBUG>(
615 "Successfully set the PFR MailBox to BMCBusy.");
616 }
617 return 0;
618}
619
620int getMBRegister(uint32_t regAddr, uint8_t& mailBoxReply)
621{
622 // Read from PFR CPLD's mailbox register
623 try
624 {
625 I2CFile mailReadDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
626
627 mailBoxReply = mailReadDev.i2cReadByteData(regAddr);
628 }
629 catch (const std::exception& e)
630 {
631 phosphor::logging::log<phosphor::logging::level::ERR>(
632 "Exception caught in mailbox reading.",
633 phosphor::logging::entry("MSG=%s", e.what()));
634 throw;
635 }
636 return 0;
637}
638
AppaRao Pulic532f552019-07-05 15:23:50 +0530639} // namespace pfr