12098dabeSJohn Wedig 22098dabeSJohn Wedig #include "estoraged.hpp" 3d32b9667SJohn Wedig #include "getConfig.hpp" 4d32b9667SJohn Wedig #include "util.hpp" 52098dabeSJohn Wedig 6d32b9667SJohn Wedig #include <boost/asio/deadline_timer.hpp> 767a47446SJohn Wedig #include <boost/asio/io_context.hpp> 8d32b9667SJohn Wedig #include <boost/asio/post.hpp> 9d32b9667SJohn Wedig #include <boost/container/flat_map.hpp> 10d32b9667SJohn Wedig #include <boost/container/throw_exception.hpp> 114e13b0a1SJohn Edward Broadbent #include <phosphor-logging/lg2.hpp> 1267a47446SJohn Wedig #include <sdbusplus/asio/connection.hpp> 1367a47446SJohn Wedig #include <sdbusplus/asio/object_server.hpp> 142098dabeSJohn Wedig #include <sdbusplus/bus.hpp> 15d32b9667SJohn Wedig #include <sdbusplus/bus/match.hpp> 16e35e7361SJohn Edward Broadbent #include <util.hpp> 172098dabeSJohn Wedig 18d32b9667SJohn Wedig #include <cstdlib> 192098dabeSJohn Wedig #include <filesystem> 202098dabeSJohn Wedig #include <iostream> 2167a47446SJohn Wedig #include <memory> 22*043af59fSTom Tung #include <optional> 232098dabeSJohn Wedig #include <string> 242098dabeSJohn Wedig 25d32b9667SJohn Wedig /* 26d32b9667SJohn Wedig * Get the configuration objects from Entity Manager and create new D-Bus 27d32b9667SJohn Wedig * objects for each one. This function can be called multiple times, in case 28d32b9667SJohn Wedig * new configuration objects show up later. 29d32b9667SJohn Wedig * 30d32b9667SJohn Wedig * Note: Currently, eStoraged can only support 1 eMMC device. 31d32b9667SJohn Wedig * Additional changes will be needed to support more than 1 eMMC, or to support 32d32b9667SJohn Wedig * more types of storage devices. 33d32b9667SJohn Wedig */ 34d32b9667SJohn Wedig void createStorageObjects( 3561cf4260SJohn Wedig sdbusplus::asio::object_server& objectServer, 36d32b9667SJohn Wedig boost::container::flat_map< 37d32b9667SJohn Wedig std::string, std::unique_ptr<estoraged::EStoraged>>& storageObjects, 38d32b9667SJohn Wedig std::shared_ptr<sdbusplus::asio::connection>& dbusConnection) 392098dabeSJohn Wedig { 40d32b9667SJohn Wedig auto getter = std::make_shared<estoraged::GetStorageConfiguration>( 41d32b9667SJohn Wedig dbusConnection, 4261cf4260SJohn Wedig [&objectServer, &storageObjects]( 43d32b9667SJohn Wedig const estoraged::ManagedStorageType& storageConfigurations) { 44d32b9667SJohn Wedig size_t numConfigObj = storageConfigurations.size(); 45d32b9667SJohn Wedig if (numConfigObj > 1) 46d32b9667SJohn Wedig { 4704c28fadSPatrick Williams lg2::error("eStoraged can only manage 1 eMMC device; found {NUM}", 48d32b9667SJohn Wedig "NUM", numConfigObj, "REDFISH_MESSAGE_ID", 49d32b9667SJohn Wedig std::string("OpenBMC.0.1.CreateStorageObjectsFail")); 50d32b9667SJohn Wedig return; 512098dabeSJohn Wedig } 522098dabeSJohn Wedig 53d32b9667SJohn Wedig for (const std::pair<sdbusplus::message::object_path, 54d32b9667SJohn Wedig estoraged::StorageData>& storage : 55d32b9667SJohn Wedig storageConfigurations) 562098dabeSJohn Wedig { 57d32b9667SJohn Wedig const std::string& path = storage.first.str; 58d32b9667SJohn Wedig 59d32b9667SJohn Wedig if (storageObjects.find(path) != storageObjects.end()) 602098dabeSJohn Wedig { 61d32b9667SJohn Wedig /* 62d32b9667SJohn Wedig * We've already created this object, or at least 63d32b9667SJohn Wedig * attempted to. 64d32b9667SJohn Wedig */ 65d32b9667SJohn Wedig continue; 662098dabeSJohn Wedig } 67d32b9667SJohn Wedig 68d32b9667SJohn Wedig /* Get the properties from the config object. */ 69d32b9667SJohn Wedig const estoraged::StorageData& data = storage.second; 70d32b9667SJohn Wedig 71d32b9667SJohn Wedig /* Look for the device file. */ 72d32b9667SJohn Wedig const std::filesystem::path blockDevDir{"/sys/block"}; 73*043af59fSTom Tung auto deviceInfo = estoraged::util::findDevice(data, blockDevDir); 74*043af59fSTom Tung if (!deviceInfo) 75d32b9667SJohn Wedig { 7604c28fadSPatrick Williams lg2::error("Device not found for path {PATH}", "PATH", path, 77d32b9667SJohn Wedig "REDFISH_MESSAGE_ID", 78d32b9667SJohn Wedig std::string("OpenBMC.0.1.CreateStorageObjectsFail")); 79d32b9667SJohn Wedig /* 80d32b9667SJohn Wedig * Set a NULL pointer as a placeholder, so that we don't 81d32b9667SJohn Wedig * try and fail again later. 82d32b9667SJohn Wedig */ 83d32b9667SJohn Wedig storageObjects[path] = nullptr; 84d32b9667SJohn Wedig continue; 852098dabeSJohn Wedig } 86d32b9667SJohn Wedig 87*043af59fSTom Tung std::filesystem::path deviceFile = 88*043af59fSTom Tung std::move(deviceInfo->deviceFile); 89*043af59fSTom Tung std::filesystem::path sysfsDir = std::move(deviceInfo->sysfsDir); 90*043af59fSTom Tung std::string luksName = std::move(deviceInfo->luksName); 91*043af59fSTom Tung std::string locationCode = std::move(deviceInfo->locationCode); 92*043af59fSTom Tung uint64_t eraseMaxGeometry = deviceInfo->eraseMaxGeometry; 93*043af59fSTom Tung uint64_t eraseMinGeometry = deviceInfo->eraseMinGeometry; 94*043af59fSTom Tung 9504c28fadSPatrick Williams uint64_t size = estoraged::util::findSizeOfBlockDevice(deviceFile); 96d32b9667SJohn Wedig 97d32b9667SJohn Wedig uint8_t lifeleft = 9804c28fadSPatrick Williams estoraged::util::findPredictedMediaLifeLeftPercent(sysfsDir); 9904c28fadSPatrick Williams std::string partNumber = estoraged::util::getPartNumber(sysfsDir); 100b4838308SJohn Wedig std::string serialNumber = 101b4838308SJohn Wedig estoraged::util::getSerialNumber(sysfsDir); 102d32b9667SJohn Wedig /* Create the storage object. */ 103d32b9667SJohn Wedig storageObjects[path] = std::make_unique<estoraged::EStoraged>( 104b4838308SJohn Wedig objectServer, path, deviceFile, luksName, size, lifeleft, 105*043af59fSTom Tung partNumber, serialNumber, locationCode, eraseMaxGeometry, 106*043af59fSTom Tung eraseMinGeometry); 10704c28fadSPatrick Williams lg2::info("Created eStoraged object for path {PATH}", "PATH", path, 10804c28fadSPatrick Williams "REDFISH_MESSAGE_ID", 109d32b9667SJohn Wedig std::string("OpenBMC.0.1.CreateStorageObjects")); 110d32b9667SJohn Wedig } 111d32b9667SJohn Wedig }); 112d32b9667SJohn Wedig getter->getConfiguration(); 113d32b9667SJohn Wedig } 114d32b9667SJohn Wedig 115d32b9667SJohn Wedig int main(void) 116d32b9667SJohn Wedig { 11782897c35SEd Tanous try 11882897c35SEd Tanous { 11967a47446SJohn Wedig // setup connection to dbus 12067a47446SJohn Wedig boost::asio::io_context io; 12167a47446SJohn Wedig auto conn = std::make_shared<sdbusplus::asio::connection>(io); 12267a47446SJohn Wedig // request D-Bus server name. 123d32b9667SJohn Wedig conn->request_name("xyz.openbmc_project.eStoraged"); 124d32b9667SJohn Wedig sdbusplus::asio::object_server server(conn); 125d32b9667SJohn Wedig boost::container::flat_map<std::string, 126d32b9667SJohn Wedig std::unique_ptr<estoraged::EStoraged>> 127d32b9667SJohn Wedig storageObjects; 1282098dabeSJohn Wedig 12961cf4260SJohn Wedig boost::asio::post( 13061cf4260SJohn Wedig io, [&]() { createStorageObjects(server, storageObjects, conn); }); 131d32b9667SJohn Wedig 132d32b9667SJohn Wedig /* 133d32b9667SJohn Wedig * Set up an event handler to process any new configuration objects 134d32b9667SJohn Wedig * that show up later. 135d32b9667SJohn Wedig */ 136d32b9667SJohn Wedig boost::asio::deadline_timer filterTimer(io); 137e3ef765dSPatrick Williams std::function<void(sdbusplus::message_t&)> eventHandler = 138e3ef765dSPatrick Williams [&](sdbusplus::message_t& message) { 139d32b9667SJohn Wedig if (message.is_method_error()) 140d32b9667SJohn Wedig { 141d32b9667SJohn Wedig lg2::error("eventHandler callback method error"); 142d32b9667SJohn Wedig return; 143d32b9667SJohn Wedig } 144d32b9667SJohn Wedig /* 145d32b9667SJohn Wedig * This implicitly cancels the timer, if it's already pending. 146d32b9667SJohn Wedig * If there's a burst of events within a short period, we want 147d32b9667SJohn Wedig * to handle them all at once. So, we will wait this long for no 148d32b9667SJohn Wedig * more events to occur, before processing them. 149d32b9667SJohn Wedig */ 150d32b9667SJohn Wedig filterTimer.expires_from_now(boost::posix_time::seconds(1)); 151d32b9667SJohn Wedig 15204c28fadSPatrick Williams filterTimer.async_wait([&](const boost::system::error_code& ec) { 153d32b9667SJohn Wedig if (ec == boost::asio::error::operation_aborted) 154d32b9667SJohn Wedig { 155d32b9667SJohn Wedig /* we were canceled */ 156d32b9667SJohn Wedig return; 157d32b9667SJohn Wedig } 158d32b9667SJohn Wedig if (ec) 159d32b9667SJohn Wedig { 160d32b9667SJohn Wedig lg2::error("timer error"); 161d32b9667SJohn Wedig return; 162d32b9667SJohn Wedig } 16361cf4260SJohn Wedig createStorageObjects(server, storageObjects, conn); 164d32b9667SJohn Wedig }); 165d32b9667SJohn Wedig }; 166d32b9667SJohn Wedig 167e3ef765dSPatrick Williams auto match = std::make_unique<sdbusplus::bus::match_t>( 168e3ef765dSPatrick Williams static_cast<sdbusplus::bus_t&>(*conn), 169d32b9667SJohn Wedig "type='signal',member='PropertiesChanged',path_namespace='" + 170d32b9667SJohn Wedig std::string("/xyz/openbmc_project/inventory") + 171d32b9667SJohn Wedig "',arg0namespace='" + estoraged::emmcConfigInterface + "'", 172d32b9667SJohn Wedig eventHandler); 173d32b9667SJohn Wedig 1744e13b0a1SJohn Edward Broadbent lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID", 175e6ffe704SJohn Edward Broadbent std::string("OpenBMC.1.0.ServiceStarted")); 1762098dabeSJohn Wedig 17767a47446SJohn Wedig io.run(); 17867a47446SJohn Wedig return 0; 17982897c35SEd Tanous } 18082897c35SEd Tanous catch (const std::exception& e) 18182897c35SEd Tanous { 18282897c35SEd Tanous lg2::error(e.what(), "REDFISH_MESSAGE_ID", 18382897c35SEd Tanous std::string("OpenBMC.1.0.ServiceException")); 1842098dabeSJohn Wedig 18582897c35SEd Tanous return 2; 18682897c35SEd Tanous } 1872098dabeSJohn Wedig return 1; 1882098dabeSJohn Wedig } 189