xref: /openbmc/estoraged/src/util.cpp (revision 5d799bb9)
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