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