1a6e3b99dSJohn Edward Broadbent #include "util.hpp" 2a6e3b99dSJohn Edward Broadbent 3a6e3b99dSJohn Edward Broadbent #include <linux/fs.h> 4a6e3b99dSJohn Edward Broadbent 5a6e3b99dSJohn Edward Broadbent #include <phosphor-logging/lg2.hpp> 6a6e3b99dSJohn Edward Broadbent #include <stdplus/fd/create.hpp> 7a6e3b99dSJohn Edward Broadbent #include <stdplus/fd/managed.hpp> 8a6e3b99dSJohn Edward Broadbent #include <stdplus/handle/managed.hpp> 9a6e3b99dSJohn Edward Broadbent #include <xyz/openbmc_project/Common/error.hpp> 10a6e3b99dSJohn Edward Broadbent 11*5d799bb9SJohn Edward Broadbent #include <fstream> 12*5d799bb9SJohn Edward Broadbent #include <iostream> 13*5d799bb9SJohn Edward Broadbent #include <string> 14a6e3b99dSJohn Edward Broadbent 15a6e3b99dSJohn Edward Broadbent namespace estoraged 16a6e3b99dSJohn Edward Broadbent { 17a6e3b99dSJohn Edward Broadbent namespace util 18a6e3b99dSJohn Edward Broadbent { 19a6e3b99dSJohn Edward Broadbent using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 20a6e3b99dSJohn Edward Broadbent using ::stdplus::fd::ManagedFd; 21a6e3b99dSJohn Edward Broadbent 22*5d799bb9SJohn Edward Broadbent uint64_t findSizeOfBlockDevice(const std::string& devPath) 23a6e3b99dSJohn Edward Broadbent { 24a6e3b99dSJohn Edward Broadbent ManagedFd fd; 25a6e3b99dSJohn Edward Broadbent uint64_t bytes = 0; 26a6e3b99dSJohn Edward Broadbent try 27a6e3b99dSJohn Edward Broadbent { 28a6e3b99dSJohn Edward Broadbent // open block dev 29a6e3b99dSJohn Edward Broadbent fd = stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly); 30a6e3b99dSJohn Edward Broadbent // get block size 31a6e3b99dSJohn Edward Broadbent fd.ioctl(BLKGETSIZE64, &bytes); 32a6e3b99dSJohn Edward Broadbent } 33a6e3b99dSJohn Edward Broadbent catch (...) 34a6e3b99dSJohn Edward Broadbent { 35a6e3b99dSJohn Edward Broadbent lg2::error("erase unable to open blockdev", "REDFISH_MESSAGE_ID", 36a6e3b99dSJohn Edward Broadbent std::string("OpenBMC.0.1.DriveEraseFailure"), 37a6e3b99dSJohn Edward Broadbent "REDFISH_MESSAGE_ARGS", std::to_string(fd.get())); 38a6e3b99dSJohn Edward Broadbent throw InternalFailure(); 39a6e3b99dSJohn Edward Broadbent } 40a6e3b99dSJohn Edward Broadbent return bytes; 41a6e3b99dSJohn Edward Broadbent } 42a6e3b99dSJohn Edward Broadbent 43*5d799bb9SJohn Edward Broadbent uint8_t findPredictedMediaLifeLeftPercent(const std::string& sysfsPath) 44*5d799bb9SJohn Edward Broadbent { 45*5d799bb9SJohn Edward Broadbent // The eMMC spec defines two estimates for the life span of the device 46*5d799bb9SJohn Edward Broadbent // in the extended CSD field 269 and 268, named estimate A and estimate B. 47*5d799bb9SJohn Edward Broadbent // Linux exposes the values in the /life_time node. 48*5d799bb9SJohn Edward Broadbent // estimate A is for A type memory 49*5d799bb9SJohn Edward Broadbent // estimate B is for B type memory 50*5d799bb9SJohn Edward Broadbent // 51*5d799bb9SJohn Edward Broadbent // the estimate are encoded as such 52*5d799bb9SJohn Edward Broadbent // 0x01 <=> 0% - 10% device life time used 53*5d799bb9SJohn Edward Broadbent // 0x02 <=> 10% -20% device life time used 54*5d799bb9SJohn Edward Broadbent // ... 55*5d799bb9SJohn Edward Broadbent // 0x0A <=> 90% - 100% device life time used 56*5d799bb9SJohn Edward Broadbent // 0x0B <=> Exceeded its maximum estimated device life time 57*5d799bb9SJohn Edward Broadbent 58*5d799bb9SJohn Edward Broadbent uint16_t estA = 0, estB = 0; 59*5d799bb9SJohn Edward Broadbent std::ifstream lifeTimeFile; 60*5d799bb9SJohn Edward Broadbent try 61*5d799bb9SJohn Edward Broadbent { 62*5d799bb9SJohn Edward Broadbent lifeTimeFile.open(sysfsPath + "/life_time", std::ios_base::in); 63*5d799bb9SJohn Edward Broadbent lifeTimeFile >> std::hex >> estA; 64*5d799bb9SJohn Edward Broadbent lifeTimeFile >> std::hex >> estB; 65*5d799bb9SJohn Edward Broadbent if ((estA == 0) || (estA > 11) || (estB == 0) || (estB > 11)) 66*5d799bb9SJohn Edward Broadbent { 67*5d799bb9SJohn Edward Broadbent throw InternalFailure(); 68*5d799bb9SJohn Edward Broadbent } 69*5d799bb9SJohn Edward Broadbent } 70*5d799bb9SJohn Edward Broadbent catch (...) 71*5d799bb9SJohn Edward Broadbent { 72*5d799bb9SJohn Edward Broadbent lg2::error("Unable to read sysfs", "REDFISH_MESSAGE_ID", 73*5d799bb9SJohn Edward Broadbent std::string("OpenBMC.0.1.DriveEraseFailure")); 74*5d799bb9SJohn Edward Broadbent lifeTimeFile.close(); 75*5d799bb9SJohn Edward Broadbent return 255; 76*5d799bb9SJohn Edward Broadbent } 77*5d799bb9SJohn Edward Broadbent lifeTimeFile.close(); 78*5d799bb9SJohn Edward Broadbent // we are returning lowest LifeLeftPercent 79*5d799bb9SJohn Edward Broadbent uint8_t maxLifeUsed = 0; 80*5d799bb9SJohn Edward Broadbent if (estA > estB) 81*5d799bb9SJohn Edward Broadbent { 82*5d799bb9SJohn Edward Broadbent maxLifeUsed = estA; 83*5d799bb9SJohn Edward Broadbent } 84*5d799bb9SJohn Edward Broadbent else 85*5d799bb9SJohn Edward Broadbent { 86*5d799bb9SJohn Edward Broadbent maxLifeUsed = estB; 87*5d799bb9SJohn Edward Broadbent } 88*5d799bb9SJohn Edward Broadbent 89*5d799bb9SJohn Edward Broadbent return static_cast<uint8_t>(11 - maxLifeUsed) * 10; 90*5d799bb9SJohn Edward Broadbent } 91*5d799bb9SJohn Edward Broadbent 92a6e3b99dSJohn Edward Broadbent } // namespace util 93a6e3b99dSJohn Edward Broadbent 94a6e3b99dSJohn Edward Broadbent } // namespace estoraged 95