blob: 4b366bb926f02d888083563f59dce84c91ee9ed7 [file] [log] [blame]
#include "util.hpp"
#include "getConfig.hpp"
#include <linux/fs.h>
#include <phosphor-logging/lg2.hpp>
#include <stdplus/fd/create.hpp>
#include <stdplus/fd/managed.hpp>
#include <stdplus/handle/managed.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
namespace estoraged
{
namespace util
{
using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
using ::stdplus::fd::ManagedFd;
uint64_t findSizeOfBlockDevice(const std::string& devPath)
{
ManagedFd fd;
uint64_t bytes = 0;
try
{
// open block dev
fd = stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly);
// get block size
fd.ioctl(BLKGETSIZE64, &bytes);
}
catch (...)
{
lg2::error("erase unable to open blockdev", "REDFISH_MESSAGE_ID",
std::string("OpenBMC.0.1.DriveEraseFailure"),
"REDFISH_MESSAGE_ARGS", std::to_string(fd.get()));
throw InternalFailure();
}
return bytes;
}
uint8_t findPredictedMediaLifeLeftPercent(const std::string& sysfsPath)
{
// The eMMC spec defines two estimates for the life span of the device
// in the extended CSD field 269 and 268, named estimate A and estimate B.
// Linux exposes the values in the /life_time node.
// estimate A is for A type memory
// estimate B is for B type memory
//
// the estimate are encoded as such
// 0x01 <=> 0% - 10% device life time used
// 0x02 <=> 10% -20% device life time used
// ...
// 0x0A <=> 90% - 100% device life time used
// 0x0B <=> Exceeded its maximum estimated device life time
uint16_t estA = 0, estB = 0;
std::ifstream lifeTimeFile;
try
{
lifeTimeFile.open(sysfsPath + "/life_time", std::ios_base::in);
lifeTimeFile >> std::hex >> estA;
lifeTimeFile >> std::hex >> estB;
if ((estA == 0) || (estA > 11) || (estB == 0) || (estB > 11))
{
throw InternalFailure();
}
}
catch (...)
{
lg2::error("Unable to read sysfs", "REDFISH_MESSAGE_ID",
std::string("OpenBMC.0.1.DriveEraseFailure"));
lifeTimeFile.close();
return 255;
}
lifeTimeFile.close();
// we are returning lowest LifeLeftPercent
uint8_t maxLifeUsed = 0;
if (estA > estB)
{
maxLifeUsed = estA;
}
else
{
maxLifeUsed = estB;
}
return static_cast<uint8_t>(11 - maxLifeUsed) * 10;
}
bool findDevice(const StorageData& data, const std::filesystem::path& searchDir,
std::filesystem::path& deviceFile,
std::filesystem::path& sysfsDir, std::string& luksName)
{
/* Check what type of storage device this is. */
estoraged::BasicVariantType typeVariant;
try
{
/* The EntityManager config should have this property set. */
typeVariant = data.at("Type");
}
catch (const boost::container::out_of_range& e)
{
lg2::error("Could not read device type", "REDFISH_MESSAGE_ID",
std::string("OpenBMC.0.1.FindDeviceFail"));
return false;
}
/*
* Currently, we only support eMMC, so report an error for any other device
* types.
*/
std::string type = std::get<std::string>(typeVariant);
if (type.compare("EmmcDevice") != 0)
{
lg2::error("Unsupported device type {TYPE}", "TYPE", type,
"REDFISH_MESSAGE_ID",
std::string("OpenBMC.0.1.FindDeviceFail"));
return false;
}
/* Look for the eMMC in the specified searchDir directory. */
for (auto const& dirEntry : std::filesystem::directory_iterator{searchDir})
{
std::filesystem::path curDevice(dirEntry.path().filename());
if (curDevice.string().starts_with("mmcblk"))
{
sysfsDir = dirEntry.path();
sysfsDir /= "device";
deviceFile = "/dev";
deviceFile /= curDevice;
luksName = "luks-" + curDevice.string();
return true;
}
}
/* Device wasn't found. */
return false;
}
} // namespace util
} // namespace estoraged