blob: 2f32c02738c4c1afec4526672f9084811e2eb3bb [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 Wedigb4838302022-07-22 13:51:16 -070095std::string getPartNumber(const std::filesystem::path& sysfsPath)
96{
97 std::ifstream partNameFile;
98 std::string partName;
99 try
100 {
101 std::filesystem::path namePath(sysfsPath);
102 namePath /= "name";
103 partNameFile.open(namePath, std::ios_base::in);
104 partNameFile >> partName;
105 }
106 catch (...)
107 {
108 lg2::error("Unable to read sysfs", "REDFISH_MESSAGE_ID",
109 std::string("OpenBMC.0.1.PartNumberFailure"));
110 }
111 partNameFile.close();
112 if (partName.empty())
113 {
114 partName = "unknown";
115 }
116
117 return partName;
118}
119
120std::string getSerialNumber(const std::filesystem::path& sysfsPath)
121{
122 std::ifstream serialNumberFile;
123 std::string serialNumber;
124 try
125 {
126 std::filesystem::path serialPath(sysfsPath);
127 serialPath /= "serial";
128 serialNumberFile.open(serialPath, std::ios_base::in);
129 serialNumberFile >> serialNumber;
130 }
131 catch (...)
132 {
133 lg2::error("Unable to read sysfs", "REDFISH_MESSAGE_ID",
134 std::string("OpenBMC.0.1.SerialNumberFailure"));
135 }
136 serialNumberFile.close();
137 if (serialNumber.empty())
138 {
139 serialNumber = "unknown";
140 }
141
142 return serialNumber;
143}
144
John Wedigd32b9662022-04-13 18:12:25 -0700145bool findDevice(const StorageData& data, const std::filesystem::path& searchDir,
146 std::filesystem::path& deviceFile,
Rahul Kapoor19825052023-05-27 01:52:23 +0000147 std::filesystem::path& sysfsDir, std::string& luksName,
148 std::string& locationCode)
John Wedigd32b9662022-04-13 18:12:25 -0700149{
150 /* Check what type of storage device this is. */
151 estoraged::BasicVariantType typeVariant;
152 try
153 {
154 /* The EntityManager config should have this property set. */
155 typeVariant = data.at("Type");
156 }
157 catch (const boost::container::out_of_range& e)
158 {
159 lg2::error("Could not read device type", "REDFISH_MESSAGE_ID",
160 std::string("OpenBMC.0.1.FindDeviceFail"));
161 return false;
162 }
163
Rahul Kapoor19825052023-05-27 01:52:23 +0000164 /* Check if location code/ silkscreen name is provided for the drive. */
165 auto findLocationCode = data.find("LocationCode");
166 if (findLocationCode != data.end())
167 {
168 const std::string* locationCodePtr =
169 std::get_if<std::string>(&findLocationCode->second);
170 if (locationCodePtr != nullptr)
171 {
172 locationCode = *locationCodePtr;
173 }
174 }
175
John Wedigd32b9662022-04-13 18:12:25 -0700176 /*
177 * Currently, we only support eMMC, so report an error for any other device
178 * types.
179 */
180 std::string type = std::get<std::string>(typeVariant);
181 if (type.compare("EmmcDevice") != 0)
182 {
183 lg2::error("Unsupported device type {TYPE}", "TYPE", type,
184 "REDFISH_MESSAGE_ID",
185 std::string("OpenBMC.0.1.FindDeviceFail"));
186 return false;
187 }
188
189 /* Look for the eMMC in the specified searchDir directory. */
Patrick Williams04c28fa2023-05-10 07:51:24 -0500190 for (const auto& dirEntry : std::filesystem::directory_iterator{searchDir})
John Wedigd32b9662022-04-13 18:12:25 -0700191 {
John Wedigf78215f2022-06-07 13:39:22 -0700192 /*
193 * We will look at the 'type' file to determine if this is an MMC
194 * device.
195 */
196 std::filesystem::path curPath(dirEntry.path());
197 curPath /= "device/type";
198 if (!std::filesystem::exists(curPath))
John Wedigd32b9662022-04-13 18:12:25 -0700199 {
John Wedigf78215f2022-06-07 13:39:22 -0700200 /* The 'type' file doesn't exist. This must not be an eMMC. */
201 continue;
202 }
John Wedigd32b9662022-04-13 18:12:25 -0700203
John Wedigf78215f2022-06-07 13:39:22 -0700204 try
205 {
206 std::ifstream typeFile(curPath, std::ios_base::in);
207 std::string devType;
208 typeFile >> devType;
John Edward Broadbent9be2f0f2023-04-11 13:58:33 -0700209 if (devType.compare("MMC") == 0 || devType.compare("SD") == 0)
John Wedigf78215f2022-06-07 13:39:22 -0700210 {
211 /* Found it. Get the sysfs directory and device file. */
212 std::filesystem::path deviceName(dirEntry.path().filename());
John Wedigd32b9662022-04-13 18:12:25 -0700213
John Wedigf78215f2022-06-07 13:39:22 -0700214 sysfsDir = dirEntry.path();
215 sysfsDir /= "device";
216
217 deviceFile = "/dev";
218 deviceFile /= deviceName;
219
220 luksName = "luks-" + deviceName.string();
221 return true;
222 }
223 }
224 catch (...)
225 {
226 lg2::error("Failed to read device type for {PATH}", "PATH", curPath,
227 "REDFISH_MESSAGE_ID",
228 std::string("OpenBMC.0.1.FindDeviceFail"));
229 /*
230 * We will still continue searching, though. Maybe this wasn't the
231 * device we were looking for, anyway.
232 */
John Wedigd32b9662022-04-13 18:12:25 -0700233 }
234 }
235
236 /* Device wasn't found. */
237 return false;
238}
239
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700240} // namespace util
241
John Edward Broadbentd3bfa7b2022-01-13 17:41:32 -0800242} // namespace estoraged