blob: 811cbf81b006ef487a241aef35c9b722547acf25 [file] [log] [blame]
John Edward Broadbenta6e3b992022-03-17 14:33:15 -07001#include "util.hpp"
John Edward Broadbente6ffe702021-10-14 14:03:11 -07002
John Wedigd32b9662022-04-13 18:12:25 -07003#include "getConfig.hpp"
4
John Edward Broadbente6ffe702021-10-14 14:03:11 -07005#include <linux/fs.h>
6
7#include <phosphor-logging/lg2.hpp>
8#include <stdplus/fd/create.hpp>
9#include <stdplus/fd/managed.hpp>
10#include <stdplus/handle/managed.hpp>
John Wedig972c3fa2021-12-29 17:30:41 -080011#include <xyz/openbmc_project/Common/error.hpp>
John Edward Broadbente6ffe702021-10-14 14:03:11 -070012
John Wedigd32b9662022-04-13 18:12:25 -070013#include <filesystem>
John Edward Broadbent5d799bb2022-03-22 16:14:24 -070014#include <fstream>
15#include <iostream>
16#include <string>
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070017
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -080018namespace estoraged
19{
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070020namespace util
21{
22using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
23using ::stdplus::fd::ManagedFd;
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -080024
John Edward Broadbent5d799bb2022-03-22 16:14:24 -070025uint64_t findSizeOfBlockDevice(const std::string& devPath)
John Edward Broadbente6ffe702021-10-14 14:03:11 -070026{
27 ManagedFd fd;
Ed Tanous82897c32022-02-21 14:11:59 -080028 uint64_t bytes = 0;
John Edward Broadbente6ffe702021-10-14 14:03:11 -070029 try
30 {
31 // open block dev
32 fd = stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly);
33 // get block size
34 fd.ioctl(BLKGETSIZE64, &bytes);
35 }
36 catch (...)
37 {
38 lg2::error("erase unable to open blockdev", "REDFISH_MESSAGE_ID",
39 std::string("OpenBMC.0.1.DriveEraseFailure"),
40 "REDFISH_MESSAGE_ARGS", std::to_string(fd.get()));
John Wedig972c3fa2021-12-29 17:30:41 -080041 throw InternalFailure();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070042 }
43 return bytes;
44}
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -080045
John Edward Broadbent5d799bb2022-03-22 16:14:24 -070046uint8_t findPredictedMediaLifeLeftPercent(const std::string& sysfsPath)
47{
48 // The eMMC spec defines two estimates for the life span of the device
49 // in the extended CSD field 269 and 268, named estimate A and estimate B.
50 // Linux exposes the values in the /life_time node.
51 // estimate A is for A type memory
52 // estimate B is for B type memory
53 //
54 // the estimate are encoded as such
55 // 0x01 <=> 0% - 10% device life time used
56 // 0x02 <=> 10% -20% device life time used
57 // ...
58 // 0x0A <=> 90% - 100% device life time used
59 // 0x0B <=> Exceeded its maximum estimated device life time
60
61 uint16_t estA = 0, estB = 0;
62 std::ifstream lifeTimeFile;
63 try
64 {
65 lifeTimeFile.open(sysfsPath + "/life_time", std::ios_base::in);
66 lifeTimeFile >> std::hex >> estA;
67 lifeTimeFile >> std::hex >> estB;
68 if ((estA == 0) || (estA > 11) || (estB == 0) || (estB > 11))
69 {
70 throw InternalFailure();
71 }
72 }
73 catch (...)
74 {
75 lg2::error("Unable to read sysfs", "REDFISH_MESSAGE_ID",
76 std::string("OpenBMC.0.1.DriveEraseFailure"));
77 lifeTimeFile.close();
78 return 255;
79 }
80 lifeTimeFile.close();
81 // we are returning lowest LifeLeftPercent
82 uint8_t maxLifeUsed = 0;
83 if (estA > estB)
84 {
85 maxLifeUsed = estA;
86 }
87 else
88 {
89 maxLifeUsed = estB;
90 }
91
92 return static_cast<uint8_t>(11 - maxLifeUsed) * 10;
93}
94
John Wedigd32b9662022-04-13 18:12:25 -070095bool findDevice(const StorageData& data, const std::filesystem::path& searchDir,
96 std::filesystem::path& deviceFile,
97 std::filesystem::path& sysfsDir, std::string& luksName)
98{
99 /* Check what type of storage device this is. */
100 estoraged::BasicVariantType typeVariant;
101 try
102 {
103 /* The EntityManager config should have this property set. */
104 typeVariant = data.at("Type");
105 }
106 catch (const boost::container::out_of_range& e)
107 {
108 lg2::error("Could not read device type", "REDFISH_MESSAGE_ID",
109 std::string("OpenBMC.0.1.FindDeviceFail"));
110 return false;
111 }
112
113 /*
114 * Currently, we only support eMMC, so report an error for any other device
115 * types.
116 */
117 std::string type = std::get<std::string>(typeVariant);
118 if (type.compare("EmmcDevice") != 0)
119 {
120 lg2::error("Unsupported device type {TYPE}", "TYPE", type,
121 "REDFISH_MESSAGE_ID",
122 std::string("OpenBMC.0.1.FindDeviceFail"));
123 return false;
124 }
125
126 /* Look for the eMMC in the specified searchDir directory. */
127 for (auto const& dirEntry : std::filesystem::directory_iterator{searchDir})
128 {
John Wedigf78215f2022-06-07 13:39:22 -0700129 /*
130 * We will look at the 'type' file to determine if this is an MMC
131 * device.
132 */
133 std::filesystem::path curPath(dirEntry.path());
134 curPath /= "device/type";
135 if (!std::filesystem::exists(curPath))
John Wedigd32b9662022-04-13 18:12:25 -0700136 {
John Wedigf78215f2022-06-07 13:39:22 -0700137 /* The 'type' file doesn't exist. This must not be an eMMC. */
138 continue;
139 }
John Wedigd32b9662022-04-13 18:12:25 -0700140
John Wedigf78215f2022-06-07 13:39:22 -0700141 try
142 {
143 std::ifstream typeFile(curPath, std::ios_base::in);
144 std::string devType;
145 typeFile >> devType;
146 if (devType.compare("MMC") == 0)
147 {
148 /* Found it. Get the sysfs directory and device file. */
149 std::filesystem::path deviceName(dirEntry.path().filename());
John Wedigd32b9662022-04-13 18:12:25 -0700150
John Wedigf78215f2022-06-07 13:39:22 -0700151 sysfsDir = dirEntry.path();
152 sysfsDir /= "device";
153
154 deviceFile = "/dev";
155 deviceFile /= deviceName;
156
157 luksName = "luks-" + deviceName.string();
158 return true;
159 }
160 }
161 catch (...)
162 {
163 lg2::error("Failed to read device type for {PATH}", "PATH", curPath,
164 "REDFISH_MESSAGE_ID",
165 std::string("OpenBMC.0.1.FindDeviceFail"));
166 /*
167 * We will still continue searching, though. Maybe this wasn't the
168 * device we were looking for, anyway.
169 */
John Wedigd32b9662022-04-13 18:12:25 -0700170 }
171 }
172
173 /* Device wasn't found. */
174 return false;
175}
176
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700177} // namespace util
178
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -0800179} // namespace estoraged