Get eraseMaxGeometry and eraseMinGeometry from dbus

Also, make findDevice return output parameters based on RVO.

With the change like in EntityManager JSON:
```
{
    "Name": "example_emmc",
    "Type": "EmmcDevice",
    "LocationCode": "location"
    "EraseMaxGeometry": 10000000000,
    "EraseMinGeometry": 5000000000,
}
```
and geometry values will be set to estoraged.

Tested:
- unit test pass:
```
5/7 util_test                        OK              0.05s
```

Change-Id: Ia8499af2168c7e740558978273fc80456eb29282
Signed-off-by: Tom Tung <shes050117@gmail.com>
diff --git a/include/estoraged.hpp b/include/estoraged.hpp
index 871fdca..ec8f467 100644
--- a/include/estoraged.hpp
+++ b/include/estoraged.hpp
@@ -44,6 +44,8 @@
      *  @param[in] partNumber - part number for the storage device
      *  @param[in] serialNumber - serial number for the storage device
      *  @param[in] locationCode - location code for the storage device
+     *  @param[in] eraseMaxGeometry - max geometry to erase if it's specified
+     *  @param[in] eraseMinGeometry - min geometry to erase if it's specified
      *  @param[in] cryptInterface - (optional) pointer to CryptsetupInterface
      *    object
      *  @param[in] fsInterface - (optional) pointer to FilesystemInterface
@@ -53,7 +55,8 @@
               const std::string& configPath, const std::string& devPath,
               const std::string& luksName, uint64_t size, uint8_t lifeTime,
               const std::string& partNumber, const std::string& serialNumber,
-              const std::string& locationCode,
+              const std::string& locationCode, uint64_t eraseMaxGeometry,
+              uint64_t eraseMinGeometry,
               std::unique_ptr<CryptsetupInterface> cryptInterface =
                   std::make_unique<Cryptsetup>(),
               std::unique_ptr<FilesystemInterface> fsInterface =
@@ -118,6 +121,12 @@
     /** @brief Mount point for the filesystem. */
     std::string mountPoint;
 
+    /** @brief Max geometry to erase. */
+    uint64_t eraseMaxGeometry;
+
+    /** @brief Min geometry to erase. */
+    uint64_t eraseMinGeometry;
+
     /** @brief Indicates whether the LUKS device is currently locked. */
     bool lockedProperty{false};
 
diff --git a/include/util.hpp b/include/util.hpp
index ff38cdd..8f5a0ff 100644
--- a/include/util.hpp
+++ b/include/util.hpp
@@ -2,6 +2,7 @@
 #include "getConfig.hpp"
 
 #include <filesystem>
+#include <optional>
 #include <string>
 
 namespace estoraged
@@ -9,6 +10,25 @@
 namespace util
 {
 
+struct DeviceInfo
+{
+    std::filesystem::path deviceFile;
+    std::filesystem::path sysfsDir;
+    std::string luksName;
+    std::string locationCode;
+    uint64_t eraseMaxGeometry;
+    uint64_t eraseMinGeometry;
+
+    DeviceInfo(std::filesystem::path& deviceFile,
+               std::filesystem::path& sysfsDir, std::string& luksName,
+               std::string& locationCode, uint64_t eraseMaxGeometry,
+               uint64_t eraseMinGeometry) :
+        deviceFile(deviceFile),
+        sysfsDir(sysfsDir), luksName(luksName), locationCode(locationCode),
+        eraseMaxGeometry(eraseMaxGeometry), eraseMinGeometry(eraseMinGeometry)
+    {}
+};
+
 /** @brief finds the size of the linux block device in bytes
  *  @param[in] devpath - the name of the linux block device
  *  @return size of a block device using the devPath
@@ -43,17 +63,11 @@
  *  @param[in] data - map of properties from the config object.
  *  @param[in] searchDir - directory to search for devices in sysfs, e.g.
  *    /sys/block
- *  @param[out] deviceFile - device file that was found, e.g. /dev/mmcblk0.
- *  @param[out] sysfsDir - directory containing the sysfs entries for this
- *    device.
- *  @param[out] luksName - name of the encrypted LUKS device.
- *
- *  @return True if the device was found. False otherwise.
+ *  @return DeviceInfo - metadata for the device if device is found. Null
+ *  otherwise.
  */
-bool findDevice(const StorageData& data, const std::filesystem::path& searchDir,
-                std::filesystem::path& deviceFile,
-                std::filesystem::path& sysfsDir, std::string& luksName,
-                std::string& locationCode);
+std::optional<DeviceInfo> findDevice(const StorageData& data,
+                                     const std::filesystem::path& searchDir);
 
 } // namespace util
 
diff --git a/include/verifyDriveGeometry.hpp b/include/verifyDriveGeometry.hpp
index 5d17957..144dd8d 100644
--- a/include/verifyDriveGeometry.hpp
+++ b/include/verifyDriveGeometry.hpp
@@ -20,13 +20,17 @@
     /** @brief Test if input is in between the max and min expected sizes,
      * and throws errors accordingly.
      *
-     *  @param[in] bytes - Size of the block device
+     *  @param[in] eraseMaxGeometry - the max expected size to erase.
+     *  @param[in] eraseMinGeometry - the min expected size to erase.
+     *  @param[in] bytes - Size of the block device.
      */
-    void geometryOkay()
+    void geometryOkay(uint64_t eraseMaxGeometry, uint64_t eraseMinGemoetry)
     {
-        geometryOkay(util::findSizeOfBlockDevice(devPath));
+        geometryOkay(eraseMaxGeometry, eraseMinGemoetry,
+                     util::findSizeOfBlockDevice(devPath));
     }
-    void geometryOkay(uint64_t bytes);
+    void geometryOkay(uint64_t eraseMaxGeometry, uint64_t eraseMinGemoetry,
+                      uint64_t bytes);
 };
 
 } // namespace estoraged
diff --git a/src/erase/verifyDriveGeometry.cpp b/src/erase/verifyDriveGeometry.cpp
index 446bee9..359135e 100644
--- a/src/erase/verifyDriveGeometry.cpp
+++ b/src/erase/verifyDriveGeometry.cpp
@@ -1,7 +1,5 @@
 #include "verifyDriveGeometry.hpp"
 
-#include "estoraged_conf.hpp"
-
 #include <phosphor-logging/lg2.hpp>
 #include <xyz/openbmc_project/Common/error.hpp>
 
@@ -11,24 +9,26 @@
 {
 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 
-void VerifyDriveGeometry::geometryOkay(uint64_t bytes)
+void VerifyDriveGeometry::geometryOkay(uint64_t eraseMaxGeometry,
+                                       uint64_t eraseMinGeometry,
+                                       uint64_t bytes)
 {
-    if (bytes > ERASE_MAX_GEOMETRY)
+    if (bytes > eraseMaxGeometry)
     {
         lg2::error("Erase verify Geometry too large", "REDFISH_MESSAGE_ID",
                    std::string("OpenBMC.0.1.DriveEraseFailure"),
                    "REDFISH_MESSAGE_ARGS",
                    std::to_string(bytes) + ">" +
-                       std::to_string(ERASE_MAX_GEOMETRY));
+                       std::to_string(eraseMaxGeometry));
         throw InternalFailure();
     }
-    if (bytes < ERASE_MIN_GEOMETRY)
+    if (bytes < eraseMinGeometry)
     {
         lg2::error(
             "eStorageD erase verify Geometry too small", "REDFISH_MESSAGE_ID",
             std::string("OpenBMC.0.1.DriveEraseFailure"),
             "REDFISH_MESSAGE_ARGS",
-            std::to_string(bytes) + "<" + std::to_string(ERASE_MIN_GEOMETRY));
+            std::to_string(bytes) + "<" + std::to_string(eraseMinGeometry));
         throw InternalFailure();
     }
 
diff --git a/src/estoraged.cpp b/src/estoraged.cpp
index b604a7c..f9c69dc 100644
--- a/src/estoraged.cpp
+++ b/src/estoraged.cpp
@@ -37,11 +37,13 @@
                      const std::string& luksName, uint64_t size,
                      uint8_t lifeTime, const std::string& partNumber,
                      const std::string& serialNumber,
-                     const std::string& locationCode,
+                     const std::string& locationCode, uint64_t eraseMaxGeometry,
+                     uint64_t eraseMinGeometry,
                      std::unique_ptr<CryptsetupInterface> cryptInterface,
                      std::unique_ptr<FilesystemInterface> fsInterface) :
     devPath(devPath),
     containerName(luksName), mountPoint("/mnt/" + luksName + "_fs"),
+    eraseMaxGeometry(eraseMaxGeometry), eraseMinGeometry(eraseMinGeometry),
     cryptIface(std::move(cryptInterface)), fsIface(std::move(fsInterface)),
     cryptDevicePath(cryptIface->cryptGetDir() + "/" + luksName),
     objectServer(server)
@@ -185,7 +187,7 @@
         case Volume::EraseMethod::VerifyGeometry:
         {
             VerifyDriveGeometry myVerifyGeometry(devPath);
-            myVerifyGeometry.geometryOkay();
+            myVerifyGeometry.geometryOkay(eraseMaxGeometry, eraseMinGeometry);
             break;
         }
         case Volume::EraseMethod::LogicalOverWrite:
diff --git a/src/main.cpp b/src/main.cpp
index e5f9d09..088d693 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,6 +19,7 @@
 #include <filesystem>
 #include <iostream>
 #include <memory>
+#include <optional>
 #include <string>
 
 /*
@@ -69,12 +70,8 @@
 
             /* Look for the device file. */
             const std::filesystem::path blockDevDir{"/sys/block"};
-            std::filesystem::path deviceFile, sysfsDir;
-            std::string luksName, locationCode;
-            bool found = estoraged::util::findDevice(data, blockDevDir,
-                                                     deviceFile, sysfsDir,
-                                                     luksName, locationCode);
-            if (!found)
+            auto deviceInfo = estoraged::util::findDevice(data, blockDevDir);
+            if (!deviceInfo)
             {
                 lg2::error("Device not found for path {PATH}", "PATH", path,
                            "REDFISH_MESSAGE_ID",
@@ -87,6 +84,14 @@
                 continue;
             }
 
+            std::filesystem::path deviceFile =
+                std::move(deviceInfo->deviceFile);
+            std::filesystem::path sysfsDir = std::move(deviceInfo->sysfsDir);
+            std::string luksName = std::move(deviceInfo->luksName);
+            std::string locationCode = std::move(deviceInfo->locationCode);
+            uint64_t eraseMaxGeometry = deviceInfo->eraseMaxGeometry;
+            uint64_t eraseMinGeometry = deviceInfo->eraseMinGeometry;
+
             uint64_t size = estoraged::util::findSizeOfBlockDevice(deviceFile);
 
             uint8_t lifeleft =
@@ -97,7 +102,8 @@
             /* Create the storage object. */
             storageObjects[path] = std::make_unique<estoraged::EStoraged>(
                 objectServer, path, deviceFile, luksName, size, lifeleft,
-                partNumber, serialNumber, locationCode);
+                partNumber, serialNumber, locationCode, eraseMaxGeometry,
+                eraseMinGeometry);
             lg2::info("Created eStoraged object for path {PATH}", "PATH", path,
                       "REDFISH_MESSAGE_ID",
                       std::string("OpenBMC.0.1.CreateStorageObjects"));
diff --git a/src/test/erase/verifyGeometry_test.cpp b/src/test/erase/verifyGeometry_test.cpp
index 8b362f3..57feebd 100644
--- a/src/test/erase/verifyGeometry_test.cpp
+++ b/src/test/erase/verifyGeometry_test.cpp
@@ -15,21 +15,24 @@
 TEST(VerifyGeometry, TooBigFail)
 {
     VerifyDriveGeometry maxVerify("");
-    EXPECT_THROW(maxVerify.geometryOkay(ERASE_MAX_GEOMETRY + 1),
+    EXPECT_THROW(maxVerify.geometryOkay(ERASE_MAX_GEOMETRY, ERASE_MIN_GEOMETRY,
+                                        ERASE_MAX_GEOMETRY + 1),
                  InternalFailure);
 }
 
 TEST(VerifyGeometry, TooSmallFail)
 {
     VerifyDriveGeometry minVerify("");
-    EXPECT_THROW(minVerify.geometryOkay(ERASE_MIN_GEOMETRY - 1),
+    EXPECT_THROW(minVerify.geometryOkay(ERASE_MAX_GEOMETRY, ERASE_MIN_GEOMETRY,
+                                        ERASE_MIN_GEOMETRY - 1),
                  InternalFailure);
 }
 
 TEST(VerifyGeometry, pass)
 {
     VerifyDriveGeometry passVerify("");
-    EXPECT_NO_THROW(passVerify.geometryOkay(ERASE_MIN_GEOMETRY + 1));
+    EXPECT_NO_THROW(passVerify.geometryOkay(
+        ERASE_MAX_GEOMETRY, ERASE_MIN_GEOMETRY, ERASE_MIN_GEOMETRY + 1));
 }
 
 } // namespace estoraged_test
diff --git a/src/test/estoraged_test.cpp b/src/test/estoraged_test.cpp
index bd6db0d..520c7ec 100644
--- a/src/test/estoraged_test.cpp
+++ b/src/test/estoraged_test.cpp
@@ -1,6 +1,7 @@
 #include "estoraged_test.hpp"
 
 #include "estoraged.hpp"
+#include "estoraged_conf.hpp"
 
 #include <unistd.h>
 
@@ -89,7 +90,8 @@
         esObject = std::make_unique<estoraged::EStoraged>(
             *objectServer, testConfigPath, testFileName, testLuksDevName,
             testSize, testLifeTime, testPartNumber, testSerialNumber,
-            testLocationCode, std::move(cryptIface), std::move(fsIface));
+            testLocationCode, ERASE_MAX_GEOMETRY, ERASE_MIN_GEOMETRY,
+            std::move(cryptIface), std::move(fsIface));
     }
 
     void TearDown() override
diff --git a/src/test/util_test.cpp b/src/test/util_test.cpp
index 5f8dca5..708454d 100644
--- a/src/test/util_test.cpp
+++ b/src/test/util_test.cpp
@@ -1,3 +1,4 @@
+#include "estoraged_conf.hpp"
 #include "getConfig.hpp"
 
 #include <boost/container/flat_map.hpp>
@@ -131,15 +132,73 @@
     /* Look for the device file. */
     std::filesystem::path deviceFile, sysfsDir;
     std::string luksName, locationCode;
-    EXPECT_TRUE(estoraged::util::findDevice(data, std::filesystem::path("./"),
-                                            deviceFile, sysfsDir, luksName,
-                                            locationCode));
+    auto result = estoraged::util::findDevice(data,
+                                              std::filesystem::path("./"));
+    EXPECT_TRUE(result.has_value());
 
     /* Validate the results. */
-    EXPECT_EQ("/dev/mmcblk0", deviceFile.string());
-    EXPECT_EQ("./mmcblk0/device", sysfsDir.string());
-    EXPECT_EQ("luks-mmcblk0", luksName);
-    EXPECT_EQ("U102020", locationCode);
+    EXPECT_EQ("/dev/mmcblk0", result->deviceFile.string());
+    EXPECT_EQ("./mmcblk0/device", result->sysfsDir.string());
+    EXPECT_EQ("luks-mmcblk0", result->luksName);
+    EXPECT_EQ("U102020", result->locationCode);
+    EXPECT_EQ(ERASE_MAX_GEOMETRY, result->eraseMaxGeometry);
+    EXPECT_EQ(ERASE_MIN_GEOMETRY, result->eraseMinGeometry);
+
+    /* Delete the dummy files. */
+    EXPECT_EQ(3U, std::filesystem::remove_all("mmcblk0"));
+    EXPECT_EQ(3U, std::filesystem::remove_all("abc"));
+    EXPECT_EQ(2U, std::filesystem::remove_all("def"));
+}
+
+/* Test case where we successfully find the device file with updating the
+ * min/max geometry. */
+TEST(utilTest, findDeviceWithMaxAndMinGeometryPass)
+{
+    estoraged::StorageData data;
+
+    /* Set up the map of properties. */
+    data.emplace(std::string("Type"),
+                 estoraged::BasicVariantType("EmmcDevice"));
+    data.emplace(std::string("Name"), estoraged::BasicVariantType("emmc"));
+    data.emplace(std::string("LocationCode"),
+                 estoraged::BasicVariantType("U102020"));
+    data.emplace(std::string("EraseMaxGeometry"),
+                 estoraged::BasicVariantType((uint64_t)5566));
+    data.emplace(std::string("EraseMinGeometry"),
+                 estoraged::BasicVariantType((uint64_t)1234));
+
+    /* Create a dummy device. */
+    std::filesystem::create_directories("abc/device");
+    const std::string dummyTypeFileName("abc/device/type");
+    std::ofstream dummyTypeFile(dummyTypeFileName,
+                                std::ios::out | std::ios::trunc);
+    dummyTypeFile << "SSD";
+    dummyTypeFile.close();
+
+    /* Another device. */
+    std::filesystem::create_directories("def/device");
+
+    /* Create a dummy eMMC device. */
+    std::filesystem::create_directories("mmcblk0/device");
+    const std::string typeFileName("mmcblk0/device/type");
+    std::ofstream typeFile(typeFileName, std::ios::out | std::ios::trunc);
+    typeFile << "MMC";
+    typeFile.close();
+
+    /* Look for the device file. */
+    std::filesystem::path deviceFile, sysfsDir;
+    std::string luksName, locationCode;
+    auto result = estoraged::util::findDevice(data,
+                                              std::filesystem::path("./"));
+    EXPECT_TRUE(result.has_value());
+
+    /* Validate the results. */
+    EXPECT_EQ("/dev/mmcblk0", result->deviceFile.string());
+    EXPECT_EQ("./mmcblk0/device", result->sysfsDir.string());
+    EXPECT_EQ("luks-mmcblk0", result->luksName);
+    EXPECT_EQ("U102020", result->locationCode);
+    EXPECT_EQ(5566, result->eraseMaxGeometry);
+    EXPECT_EQ(1234, result->eraseMinGeometry);
 
     /* Delete the dummy files. */
     EXPECT_EQ(3U, std::filesystem::remove_all("mmcblk0"));
@@ -174,11 +233,9 @@
     typeFile.close();
 
     /* Look for the device file. */
-    std::filesystem::path deviceFile, sysfsDir;
-    std::string luksName, locationCode;
-    EXPECT_FALSE(estoraged::util::findDevice(data, std::filesystem::path("./"),
-                                             deviceFile, sysfsDir, luksName,
-                                             locationCode));
+    auto result = estoraged::util::findDevice(data,
+                                              std::filesystem::path("./"));
+    EXPECT_FALSE(result.has_value());
 
     /* Delete the dummy files. */
     EXPECT_EQ(3U, std::filesystem::remove_all("mmcblk0"));
@@ -215,11 +272,9 @@
     typeFile.close();
 
     /* Look for the device file. */
-    std::filesystem::path deviceFile, sysfsDir;
-    std::string luksName, locationCode;
-    EXPECT_FALSE(estoraged::util::findDevice(data, std::filesystem::path("./"),
-                                             deviceFile, sysfsDir, luksName,
-                                             locationCode));
+    auto result = estoraged::util::findDevice(data,
+                                              std::filesystem::path("./"));
+    EXPECT_FALSE(result.has_value());
 
     /* Delete the dummy files. */
     EXPECT_EQ(3U, std::filesystem::remove_all("mmcblk0"));
@@ -249,11 +304,9 @@
     std::filesystem::create_directories("def/device");
 
     /* Look for the device file. */
-    std::filesystem::path deviceFile, sysfsDir;
-    std::string luksName, locationCode;
-    EXPECT_FALSE(estoraged::util::findDevice(data, std::filesystem::path("./"),
-                                             deviceFile, sysfsDir, luksName,
-                                             locationCode));
+    auto result = estoraged::util::findDevice(data,
+                                              std::filesystem::path("./"));
+    EXPECT_FALSE(result.has_value());
 
     /* Delete the dummy files. */
     EXPECT_EQ(3U, std::filesystem::remove_all("abc"));
diff --git a/src/util.cpp b/src/util.cpp
index 2f32c02..d32d59c 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,5 +1,6 @@
 #include "util.hpp"
 
+#include "estoraged_conf.hpp"
 #include "getConfig.hpp"
 
 #include <linux/fs.h>
@@ -13,6 +14,7 @@
 #include <filesystem>
 #include <fstream>
 #include <iostream>
+#include <optional>
 #include <string>
 
 namespace estoraged
@@ -142,10 +144,8 @@
     return serialNumber;
 }
 
-bool findDevice(const StorageData& data, const std::filesystem::path& searchDir,
-                std::filesystem::path& deviceFile,
-                std::filesystem::path& sysfsDir, std::string& luksName,
-                std::string& locationCode)
+std::optional<DeviceInfo> findDevice(const StorageData& data,
+                                     const std::filesystem::path& searchDir)
 {
     /* Check what type of storage device this is. */
     estoraged::BasicVariantType typeVariant;
@@ -158,10 +158,11 @@
     {
         lg2::error("Could not read device type", "REDFISH_MESSAGE_ID",
                    std::string("OpenBMC.0.1.FindDeviceFail"));
-        return false;
+        return std::nullopt;
     }
 
     /* Check if location code/ silkscreen name is provided for the drive. */
+    std::string locationCode;
     auto findLocationCode = data.find("LocationCode");
     if (findLocationCode != data.end())
     {
@@ -173,6 +174,34 @@
         }
     }
 
+    /* Check if EraseMaxGeometry is provided. */
+    uint64_t eraseMaxGeometry = ERASE_MAX_GEOMETRY;
+    auto findEraseMaxGeometry = data.find("EraseMaxGeometry");
+    if (findEraseMaxGeometry != data.end())
+    {
+        const auto* eraseMaxGeometryPtr =
+            std::get_if<uint64_t>(&findEraseMaxGeometry->second);
+        if (eraseMaxGeometryPtr != nullptr)
+        {
+            lg2::info("eStorageD new eraseMaxGeometry found on system");
+            eraseMaxGeometry = *eraseMaxGeometryPtr;
+        }
+    }
+
+    /* Check if EraseMinGeometry is provided. */
+    uint64_t eraseMinGeometry = ERASE_MIN_GEOMETRY;
+    auto findEraseMinGeometry = data.find("EraseMinGeometry");
+    if (findEraseMinGeometry != data.end())
+    {
+        const auto* eraseMinGeometryPtr =
+            std::get_if<uint64_t>(&findEraseMinGeometry->second);
+        if (eraseMinGeometryPtr != nullptr)
+        {
+            lg2::info("eStorageD new eraseMinGeometry found on system");
+            eraseMinGeometry = *eraseMinGeometryPtr;
+        }
+    }
+
     /*
      * Currently, we only support eMMC, so report an error for any other device
      * types.
@@ -183,7 +212,7 @@
         lg2::error("Unsupported device type {TYPE}", "TYPE", type,
                    "REDFISH_MESSAGE_ID",
                    std::string("OpenBMC.0.1.FindDeviceFail"));
-        return false;
+        return std::nullopt;
     }
 
     /* Look for the eMMC in the specified searchDir directory. */
@@ -211,14 +240,16 @@
                 /* Found it. Get the sysfs directory and device file. */
                 std::filesystem::path deviceName(dirEntry.path().filename());
 
-                sysfsDir = dirEntry.path();
+                std::filesystem::path sysfsDir = dirEntry.path();
                 sysfsDir /= "device";
 
-                deviceFile = "/dev";
+                std::filesystem::path deviceFile = "/dev";
                 deviceFile /= deviceName;
 
-                luksName = "luks-" + deviceName.string();
-                return true;
+                std::string luksName = "luks-" + deviceName.string();
+                return DeviceInfo{deviceFile,       sysfsDir,
+                                  luksName,         locationCode,
+                                  eraseMaxGeometry, eraseMinGeometry};
             }
         }
         catch (...)
@@ -234,7 +265,7 @@
     }
 
     /* Device wasn't found. */
-    return false;
+    return std::nullopt;
 }
 
 } // namespace util