1729dae72SJennifer Lee /* 2729dae72SJennifer Lee // Copyright (c) 2018 Intel Corporation 3729dae72SJennifer Lee // 4729dae72SJennifer Lee // Licensed under the Apache License, Version 2.0 (the "License"); 5729dae72SJennifer Lee // you may not use this file except in compliance with the License. 6729dae72SJennifer Lee // You may obtain a copy of the License at 7729dae72SJennifer Lee // 8729dae72SJennifer Lee // http://www.apache.org/licenses/LICENSE-2.0 9729dae72SJennifer Lee // 10729dae72SJennifer Lee // Unless required by applicable law or agreed to in writing, software 11729dae72SJennifer Lee // distributed under the License is distributed on an "AS IS" BASIS, 12729dae72SJennifer Lee // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13729dae72SJennifer Lee // See the License for the specific language governing permissions and 14729dae72SJennifer Lee // limitations under the License. 15729dae72SJennifer Lee */ 16729dae72SJennifer Lee #pragma once 17729dae72SJennifer Lee 18729dae72SJennifer Lee #include "node.hpp" 191abe55efSEd Tanous 20729dae72SJennifer Lee #include <boost/container/flat_map.hpp> 21*87d84729SAndrew Geissler #include <utils/fw_utils.hpp> 22abf2add6SEd Tanous #include <variant> 23729dae72SJennifer Lee 241abe55efSEd Tanous namespace redfish 251abe55efSEd Tanous { 2627826b5fSEd Tanous 27acb7cfb4SJennifer Lee static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher; 28729dae72SJennifer Lee 291abe55efSEd Tanous class UpdateService : public Node 301abe55efSEd Tanous { 31729dae72SJennifer Lee public: 321abe55efSEd Tanous UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/") 331abe55efSEd Tanous { 34729dae72SJennifer Lee entityPrivileges = { 35729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 36729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 37729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 38729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 39729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 40729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 41729dae72SJennifer Lee } 42729dae72SJennifer Lee 43729dae72SJennifer Lee private: 4455c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 451abe55efSEd Tanous const std::vector<std::string> ¶ms) override 461abe55efSEd Tanous { 470f74e643SEd Tanous res.jsonValue["@odata.type"] = "#UpdateService.v1_2_0.UpdateService"; 480f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService"; 490f74e643SEd Tanous res.jsonValue["@odata.context"] = 500f74e643SEd Tanous "/redfish/v1/$metadata#UpdateService.UpdateService"; 510f74e643SEd Tanous res.jsonValue["Id"] = "UpdateService"; 520f74e643SEd Tanous res.jsonValue["Description"] = "Service for Software Update"; 530f74e643SEd Tanous res.jsonValue["Name"] = "Update Service"; 540f74e643SEd Tanous res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService"; 550f74e643SEd Tanous // UpdateService cannot be disabled 560f74e643SEd Tanous res.jsonValue["ServiceEnabled"] = true; 570f74e643SEd Tanous res.jsonValue["FirmwareInventory"] = { 580f74e643SEd Tanous {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}}; 59729dae72SJennifer Lee res.end(); 60729dae72SJennifer Lee } 611abe55efSEd Tanous static void activateImage(const std::string &objPath) 621abe55efSEd Tanous { 63acb7cfb4SJennifer Lee crow::connections::systemBus->async_method_call( 64c711bf86SEd Tanous [objPath](const boost::system::error_code error_code) { 651abe55efSEd Tanous if (error_code) 661abe55efSEd Tanous { 67acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "error_code = " << error_code; 68acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "error msg = " << error_code.message(); 69acb7cfb4SJennifer Lee } 70acb7cfb4SJennifer Lee }, 71c711bf86SEd Tanous "xyz.openbmc_project.Software.BMC.Updater", objPath, 72acb7cfb4SJennifer Lee "org.freedesktop.DBus.Properties", "Set", 73acb7cfb4SJennifer Lee "xyz.openbmc_project.Software.Activation", "RequestedActivation", 74abf2add6SEd Tanous std::variant<std::string>( 75acb7cfb4SJennifer Lee "xyz.openbmc_project.Software.Activation.RequestedActivations." 76acb7cfb4SJennifer Lee "Active")); 77acb7cfb4SJennifer Lee } 78acb7cfb4SJennifer Lee void doPost(crow::Response &res, const crow::Request &req, 791abe55efSEd Tanous const std::vector<std::string> ¶ms) override 801abe55efSEd Tanous { 81acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "doPost..."; 82acb7cfb4SJennifer Lee 83acb7cfb4SJennifer Lee // Only allow one FW update at a time 841abe55efSEd Tanous if (fwUpdateMatcher != nullptr) 851abe55efSEd Tanous { 86acb7cfb4SJennifer Lee res.addHeader("Retry-After", "30"); 87f12894f8SJason M. Bills messages::serviceTemporarilyUnavailable(res, "3"); 88acb7cfb4SJennifer Lee res.end(); 89acb7cfb4SJennifer Lee return; 90acb7cfb4SJennifer Lee } 91acb7cfb4SJennifer Lee // Make this const static so it survives outside this method 921abe55efSEd Tanous static boost::asio::deadline_timer timeout( 931abe55efSEd Tanous *req.ioService, boost::posix_time::seconds(5)); 94acb7cfb4SJennifer Lee 95acb7cfb4SJennifer Lee timeout.expires_from_now(boost::posix_time::seconds(5)); 96acb7cfb4SJennifer Lee 97acb7cfb4SJennifer Lee timeout.async_wait([&res](const boost::system::error_code &ec) { 98acb7cfb4SJennifer Lee fwUpdateMatcher = nullptr; 991abe55efSEd Tanous if (ec == boost::asio::error::operation_aborted) 1001abe55efSEd Tanous { 101acb7cfb4SJennifer Lee // expected, we were canceled before the timer completed. 102acb7cfb4SJennifer Lee return; 103acb7cfb4SJennifer Lee } 1041abe55efSEd Tanous BMCWEB_LOG_ERROR 1051abe55efSEd Tanous << "Timed out waiting for firmware object being created"; 1061abe55efSEd Tanous BMCWEB_LOG_ERROR 1071abe55efSEd Tanous << "FW image may has already been uploaded to server"; 1081abe55efSEd Tanous if (ec) 1091abe55efSEd Tanous { 110acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "Async_wait failed" << ec; 111acb7cfb4SJennifer Lee return; 112acb7cfb4SJennifer Lee } 113acb7cfb4SJennifer Lee 114f12894f8SJason M. Bills redfish::messages::internalError(res); 115acb7cfb4SJennifer Lee res.end(); 116acb7cfb4SJennifer Lee }); 117acb7cfb4SJennifer Lee 118acb7cfb4SJennifer Lee auto callback = [&res](sdbusplus::message::message &m) { 119acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Match fired"; 120acb7cfb4SJennifer Lee 1211abe55efSEd Tanous if (m.is_method_error()) 1221abe55efSEd Tanous { 123acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Dbus method error!!!"; 124acb7cfb4SJennifer Lee res.end(); 125acb7cfb4SJennifer Lee return; 126acb7cfb4SJennifer Lee } 127acb7cfb4SJennifer Lee std::vector<std::pair< 128acb7cfb4SJennifer Lee std::string, 129abf2add6SEd Tanous std::vector<std::pair<std::string, std::variant<std::string>>>>> 1303ae837c9SEd Tanous interfacesProperties; 131acb7cfb4SJennifer Lee 132c711bf86SEd Tanous sdbusplus::message::object_path objPath; 133acb7cfb4SJennifer Lee 1343ae837c9SEd Tanous m.read(objPath, interfacesProperties); // Read in the object path 135acb7cfb4SJennifer Lee // that was just created 136c711bf86SEd Tanous // std::string str_objpath = objPath.str; // keep a copy for 137acb7cfb4SJennifer Lee // constructing response message 138c711bf86SEd Tanous BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath; 1393ae837c9SEd Tanous for (auto &interface : interfacesProperties) 1401abe55efSEd Tanous { 141acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "interface = " << interface.first; 142acb7cfb4SJennifer Lee 1431abe55efSEd Tanous if (interface.first == 1441abe55efSEd Tanous "xyz.openbmc_project.Software.Activation") 1451abe55efSEd Tanous { 1461abe55efSEd Tanous // cancel timer only when 1471abe55efSEd Tanous // xyz.openbmc_project.Software.Activation interface is 1481abe55efSEd Tanous // added 149acb7cfb4SJennifer Lee boost::system::error_code ec; 150acb7cfb4SJennifer Lee timeout.cancel(ec); 1511abe55efSEd Tanous if (ec) 1521abe55efSEd Tanous { 153acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "error canceling timer " << ec; 154acb7cfb4SJennifer Lee } 155c711bf86SEd Tanous UpdateService::activateImage(objPath.str); // str_objpath); 156f12894f8SJason M. Bills redfish::messages::success(res); 157acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "ending response"; 158acb7cfb4SJennifer Lee res.end(); 159acb7cfb4SJennifer Lee fwUpdateMatcher = nullptr; 160acb7cfb4SJennifer Lee } 161acb7cfb4SJennifer Lee } 162acb7cfb4SJennifer Lee }; 163acb7cfb4SJennifer Lee 164acb7cfb4SJennifer Lee fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>( 165acb7cfb4SJennifer Lee *crow::connections::systemBus, 166acb7cfb4SJennifer Lee "interface='org.freedesktop.DBus.ObjectManager',type='signal'," 167acb7cfb4SJennifer Lee "member='InterfacesAdded',path='/xyz/openbmc_project/software'", 168acb7cfb4SJennifer Lee callback); 169acb7cfb4SJennifer Lee 170acb7cfb4SJennifer Lee std::string filepath( 171acb7cfb4SJennifer Lee "/tmp/images/" + 172acb7cfb4SJennifer Lee boost::uuids::to_string(boost::uuids::random_generator()())); 173acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Writing file to " << filepath; 174acb7cfb4SJennifer Lee std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary | 175acb7cfb4SJennifer Lee std::ofstream::trunc); 176acb7cfb4SJennifer Lee out << req.body; 177acb7cfb4SJennifer Lee out.close(); 178acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "file upload complete!!"; 179acb7cfb4SJennifer Lee } 180729dae72SJennifer Lee }; 181729dae72SJennifer Lee 1821abe55efSEd Tanous class SoftwareInventoryCollection : public Node 1831abe55efSEd Tanous { 184729dae72SJennifer Lee public: 185729dae72SJennifer Lee template <typename CrowApp> 1861abe55efSEd Tanous SoftwareInventoryCollection(CrowApp &app) : 1871abe55efSEd Tanous Node(app, "/redfish/v1/UpdateService/FirmwareInventory/") 1881abe55efSEd Tanous { 189729dae72SJennifer Lee entityPrivileges = { 190729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 191729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 192729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 193729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 194729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 195729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 196729dae72SJennifer Lee } 197729dae72SJennifer Lee 198729dae72SJennifer Lee private: 19955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 2001abe55efSEd Tanous const std::vector<std::string> ¶ms) override 2011abe55efSEd Tanous { 202c711bf86SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 2030f74e643SEd Tanous res.jsonValue["@odata.type"] = 2040f74e643SEd Tanous "#SoftwareInventoryCollection.SoftwareInventoryCollection"; 2050f74e643SEd Tanous res.jsonValue["@odata.id"] = 2060f74e643SEd Tanous "/redfish/v1/UpdateService/FirmwareInventory"; 2070f74e643SEd Tanous res.jsonValue["@odata.context"] = 2080f74e643SEd Tanous "/redfish/v1/" 2090f74e643SEd Tanous "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection"; 2100f74e643SEd Tanous res.jsonValue["Name"] = "Software Inventory Collection"; 211c711bf86SEd Tanous 212c711bf86SEd Tanous crow::connections::systemBus->async_method_call( 213c711bf86SEd Tanous [asyncResp]( 214c711bf86SEd Tanous const boost::system::error_code ec, 2156c4eb9deSJennifer Lee const std::vector<std::pair< 2161abe55efSEd Tanous std::string, std::vector<std::pair< 2171abe55efSEd Tanous std::string, std::vector<std::string>>>>> 2186c4eb9deSJennifer Lee &subtree) { 2191abe55efSEd Tanous if (ec) 2201abe55efSEd Tanous { 221f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2226c4eb9deSJennifer Lee return; 223729dae72SJennifer Lee } 224c711bf86SEd Tanous asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); 225c711bf86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 0; 2266c4eb9deSJennifer Lee 2271abe55efSEd Tanous for (auto &obj : subtree) 2281abe55efSEd Tanous { 2291abe55efSEd Tanous const std::vector< 2301abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 2316c4eb9deSJennifer Lee &connections = obj.second; 2326c4eb9deSJennifer Lee 233f4b65ab1SJennifer Lee // if can't parse fw id then return 23427826b5fSEd Tanous std::size_t idPos; 23527826b5fSEd Tanous if ((idPos = obj.first.rfind("/")) == std::string::npos) 236f4b65ab1SJennifer Lee { 237f12894f8SJason M. Bills messages::internalError(asyncResp->res); 238f4b65ab1SJennifer Lee BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!"; 239f4b65ab1SJennifer Lee return; 240f4b65ab1SJennifer Lee } 241f4b65ab1SJennifer Lee std::string swId = obj.first.substr(idPos + 1); 242f4b65ab1SJennifer Lee 2431abe55efSEd Tanous for (auto &conn : connections) 2441abe55efSEd Tanous { 245c711bf86SEd Tanous const std::string &connectionName = conn.first; 2461abe55efSEd Tanous BMCWEB_LOG_DEBUG << "connectionName = " 2471abe55efSEd Tanous << connectionName; 24855c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "obj.first = " << obj.first; 2496c4eb9deSJennifer Lee 25055c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 251f4b65ab1SJennifer Lee [asyncResp, 252f4b65ab1SJennifer Lee swId](const boost::system::error_code error_code, 253c711bf86SEd Tanous const VariantType &activation) { 2541abe55efSEd Tanous BMCWEB_LOG_DEBUG 2551abe55efSEd Tanous << "safe returned in lambda function"; 2561abe55efSEd Tanous if (error_code) 2571abe55efSEd Tanous { 258f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2596c4eb9deSJennifer Lee return; 2606c4eb9deSJennifer Lee } 261c711bf86SEd Tanous 262f4b65ab1SJennifer Lee const std::string *swActivationStatus = 263abf2add6SEd Tanous std::get_if<std::string>(&activation); 264f4b65ab1SJennifer Lee if (swActivationStatus == nullptr) 2651abe55efSEd Tanous { 266f12894f8SJason M. Bills messages::internalError(asyncResp->res); 267acb7cfb4SJennifer Lee return; 268acb7cfb4SJennifer Lee } 269f4b65ab1SJennifer Lee if (swActivationStatus != nullptr && 270f4b65ab1SJennifer Lee *swActivationStatus != 271f4b65ab1SJennifer Lee "xyz.openbmc_project.Software." 272f4b65ab1SJennifer Lee "Activation." 273f4b65ab1SJennifer Lee "Activations.Active") 2741abe55efSEd Tanous { 275f4b65ab1SJennifer Lee // The activation status of this software is 276f4b65ab1SJennifer Lee // not currently active, so does not need to 277f4b65ab1SJennifer Lee // be listed in the response 278c711bf86SEd Tanous return; 279c711bf86SEd Tanous } 280c711bf86SEd Tanous nlohmann::json &members = 281c711bf86SEd Tanous asyncResp->res.jsonValue["Members"]; 282c711bf86SEd Tanous members.push_back( 283f4b65ab1SJennifer Lee {{"@odata.id", "/redfish/v1/UpdateService/" 2841abe55efSEd Tanous "FirmwareInventory/" + 285f4b65ab1SJennifer Lee swId}}); 2861abe55efSEd Tanous asyncResp->res 2871abe55efSEd Tanous .jsonValue["Members@odata.count"] = 288c711bf86SEd Tanous members.size(); 2896c4eb9deSJennifer Lee }, 2901abe55efSEd Tanous connectionName, obj.first, 2911abe55efSEd Tanous "org.freedesktop.DBus.Properties", "Get", 2921abe55efSEd Tanous "xyz.openbmc_project.Software.Activation", 293acb7cfb4SJennifer Lee "Activation"); 2946c4eb9deSJennifer Lee } 2956c4eb9deSJennifer Lee } 296c711bf86SEd Tanous }, 297c711bf86SEd Tanous "xyz.openbmc_project.ObjectMapper", 298c711bf86SEd Tanous "/xyz/openbmc_project/object_mapper", 299c711bf86SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 300c711bf86SEd Tanous "/xyz/openbmc_project/software", int32_t(1), 3011abe55efSEd Tanous std::array<const char *, 1>{ 3021abe55efSEd Tanous "xyz.openbmc_project.Software.Version"}); 303729dae72SJennifer Lee } 304729dae72SJennifer Lee }; 305c711bf86SEd Tanous 3061abe55efSEd Tanous class SoftwareInventory : public Node 3071abe55efSEd Tanous { 308729dae72SJennifer Lee public: 309729dae72SJennifer Lee template <typename CrowApp> 3101abe55efSEd Tanous SoftwareInventory(CrowApp &app) : 3111abe55efSEd Tanous Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/", 3121abe55efSEd Tanous std::string()) 3131abe55efSEd Tanous { 314729dae72SJennifer Lee entityPrivileges = { 315729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 316729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 317729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 318729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 319729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 320729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 321729dae72SJennifer Lee } 322729dae72SJennifer Lee 323729dae72SJennifer Lee private: 324*87d84729SAndrew Geissler /* Fill related item links (i.e. bmc, bios) in for inventory */ 325*87d84729SAndrew Geissler static void getRelatedItems(std::shared_ptr<AsyncResp> aResp, 326*87d84729SAndrew Geissler const std::string &purpose) 327*87d84729SAndrew Geissler { 328*87d84729SAndrew Geissler if (purpose == fw_util::bmcPurpose) 329*87d84729SAndrew Geissler { 330*87d84729SAndrew Geissler nlohmann::json &members = aResp->res.jsonValue["RelatedItem"]; 331*87d84729SAndrew Geissler members.push_back({{"@odata.id", "/redfish/v1/Managers/bmc"}}); 332*87d84729SAndrew Geissler aResp->res.jsonValue["Members@odata.count"] = members.size(); 333*87d84729SAndrew Geissler } 334*87d84729SAndrew Geissler else if (purpose == fw_util::biosPurpose) 335*87d84729SAndrew Geissler { 336*87d84729SAndrew Geissler // TODO(geissonator) Need BIOS schema support added for this 337*87d84729SAndrew Geissler // to be valid 338*87d84729SAndrew Geissler // nlohmann::json &members = aResp->res.jsonValue["RelatedItem"]; 339*87d84729SAndrew Geissler // members.push_back( 340*87d84729SAndrew Geissler // {{"@odata.id", "/redfish/v1/Systems/system/BIOS"}}); 341*87d84729SAndrew Geissler // aResp->res.jsonValue["Members@odata.count"] = members.size(); 342*87d84729SAndrew Geissler } 343*87d84729SAndrew Geissler else 344*87d84729SAndrew Geissler { 345*87d84729SAndrew Geissler BMCWEB_LOG_ERROR << "Unknown software purpose " << purpose; 346*87d84729SAndrew Geissler } 347*87d84729SAndrew Geissler } 348*87d84729SAndrew Geissler 34955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 3501abe55efSEd Tanous const std::vector<std::string> ¶ms) override 3511abe55efSEd Tanous { 352c711bf86SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 3530f74e643SEd Tanous res.jsonValue["@odata.type"] = 3540f74e643SEd Tanous "#SoftwareInventory.v1_1_0.SoftwareInventory"; 3550f74e643SEd Tanous res.jsonValue["@odata.context"] = 3560f74e643SEd Tanous "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory"; 3570f74e643SEd Tanous res.jsonValue["Name"] = "Software Inventory"; 3580f74e643SEd Tanous res.jsonValue["Updateable"] = false; 3590f74e643SEd Tanous res.jsonValue["Status"]["Health"] = "OK"; 3600f74e643SEd Tanous res.jsonValue["Status"]["HealthRollup"] = "OK"; 3610f74e643SEd Tanous res.jsonValue["Status"]["State"] = "Enabled"; 3626c4eb9deSJennifer Lee 3631abe55efSEd Tanous if (params.size() != 1) 3641abe55efSEd Tanous { 365f12894f8SJason M. Bills messages::internalError(res); 366729dae72SJennifer Lee res.end(); 367729dae72SJennifer Lee return; 368729dae72SJennifer Lee } 369729dae72SJennifer Lee 3703ae837c9SEd Tanous std::shared_ptr<std::string> swId = 371c711bf86SEd Tanous std::make_shared<std::string>(params[0]); 372c711bf86SEd Tanous 37355c7b7a2SEd Tanous res.jsonValue["@odata.id"] = 3743ae837c9SEd Tanous "/redfish/v1/UpdateService/FirmwareInventory/" + *swId; 375c711bf86SEd Tanous 376c711bf86SEd Tanous crow::connections::systemBus->async_method_call( 3773ae837c9SEd Tanous [asyncResp, swId]( 378c711bf86SEd Tanous const boost::system::error_code ec, 3796c4eb9deSJennifer Lee const std::vector<std::pair< 3801abe55efSEd Tanous std::string, std::vector<std::pair< 3811abe55efSEd Tanous std::string, std::vector<std::string>>>>> 3826c4eb9deSJennifer Lee &subtree) { 38355c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "doGet callback..."; 3841abe55efSEd Tanous if (ec) 3851abe55efSEd Tanous { 386f12894f8SJason M. Bills messages::internalError(asyncResp->res); 3876c4eb9deSJennifer Lee return; 3886c4eb9deSJennifer Lee } 3896c4eb9deSJennifer Lee 3901abe55efSEd Tanous for (const std::pair< 3911abe55efSEd Tanous std::string, 3921abe55efSEd Tanous std::vector< 3931abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 3941abe55efSEd Tanous &obj : subtree) 3951abe55efSEd Tanous { 3963ae837c9SEd Tanous if (boost::ends_with(obj.first, *swId) != true) 3971abe55efSEd Tanous { 398acb7cfb4SJennifer Lee continue; 399acb7cfb4SJennifer Lee } 400acb7cfb4SJennifer Lee 401f4b65ab1SJennifer Lee if (obj.second.size() < 1) 4021abe55efSEd Tanous { 403acb7cfb4SJennifer Lee continue; 404acb7cfb4SJennifer Lee } 4056c4eb9deSJennifer Lee 40655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 4071abe55efSEd Tanous [asyncResp, 4083ae837c9SEd Tanous swId](const boost::system::error_code error_code, 4091abe55efSEd Tanous const boost::container::flat_map< 4101abe55efSEd Tanous std::string, VariantType> &propertiesList) { 4111abe55efSEd Tanous if (error_code) 4121abe55efSEd Tanous { 413f12894f8SJason M. Bills messages::internalError(asyncResp->res); 4146c4eb9deSJennifer Lee return; 4156c4eb9deSJennifer Lee } 4161abe55efSEd Tanous boost::container::flat_map< 4171abe55efSEd Tanous std::string, VariantType>::const_iterator it = 4186c4eb9deSJennifer Lee propertiesList.find("Purpose"); 4191abe55efSEd Tanous if (it == propertiesList.end()) 4201abe55efSEd Tanous { 4211abe55efSEd Tanous BMCWEB_LOG_DEBUG 4221abe55efSEd Tanous << "Can't find property \"Purpose\"!"; 423f12894f8SJason M. Bills messages::propertyMissing(asyncResp->res, 424f12894f8SJason M. Bills "Purpose"); 4256c4eb9deSJennifer Lee return; 4266c4eb9deSJennifer Lee } 4273ae837c9SEd Tanous const std::string *swInvPurpose = 428abf2add6SEd Tanous std::get_if<std::string>(&it->second); 4293ae837c9SEd Tanous if (swInvPurpose == nullptr) 4301abe55efSEd Tanous { 4311abe55efSEd Tanous BMCWEB_LOG_DEBUG 4321abe55efSEd Tanous << "wrong types for property\"Purpose\"!"; 433f12894f8SJason M. Bills messages::propertyValueTypeError(asyncResp->res, 434f12894f8SJason M. Bills "", "Purpose"); 435acb7cfb4SJennifer Lee return; 436acb7cfb4SJennifer Lee } 437c711bf86SEd Tanous 4383ae837c9SEd Tanous BMCWEB_LOG_DEBUG << "swInvPurpose = " 4393ae837c9SEd Tanous << *swInvPurpose; 440c711bf86SEd Tanous it = propertiesList.find("Version"); 4411abe55efSEd Tanous if (it == propertiesList.end()) 4421abe55efSEd Tanous { 4431abe55efSEd Tanous BMCWEB_LOG_DEBUG 4441abe55efSEd Tanous << "Can't find property \"Version\"!"; 445f12894f8SJason M. Bills messages::propertyMissing(asyncResp->res, 446f12894f8SJason M. Bills "Version"); 447c711bf86SEd Tanous return; 448acb7cfb4SJennifer Lee } 449acb7cfb4SJennifer Lee 450f4b65ab1SJennifer Lee BMCWEB_LOG_DEBUG << "Version found!"; 451c711bf86SEd Tanous 452f4b65ab1SJennifer Lee const std::string *version = 453abf2add6SEd Tanous std::get_if<std::string>(&it->second); 454f4b65ab1SJennifer Lee 455f4b65ab1SJennifer Lee if (version == nullptr) 4561abe55efSEd Tanous { 4571abe55efSEd Tanous BMCWEB_LOG_DEBUG 4581abe55efSEd Tanous << "Can't find property \"Version\"!"; 459f12894f8SJason M. Bills 460f12894f8SJason M. Bills messages::propertyValueTypeError(asyncResp->res, 461f12894f8SJason M. Bills "", "Version"); 4626c4eb9deSJennifer Lee return; 4636c4eb9deSJennifer Lee } 464c711bf86SEd Tanous asyncResp->res.jsonValue["Version"] = *version; 4653ae837c9SEd Tanous asyncResp->res.jsonValue["Id"] = *swId; 46654daabe7SAndrew Geissler 46754daabe7SAndrew Geissler // swInvPurpose is of format: 46854daabe7SAndrew Geissler // xyz.openbmc_project.Software.Version.VersionPurpose.ABC 46954daabe7SAndrew Geissler // Translate this to "ABC update" 47054daabe7SAndrew Geissler size_t endDesc = swInvPurpose->rfind("."); 47154daabe7SAndrew Geissler if (endDesc == std::string::npos) 47254daabe7SAndrew Geissler { 47354daabe7SAndrew Geissler messages::internalError(asyncResp->res); 47454daabe7SAndrew Geissler return; 47554daabe7SAndrew Geissler } 47654daabe7SAndrew Geissler endDesc++; 47754daabe7SAndrew Geissler if (endDesc >= swInvPurpose->size()) 47854daabe7SAndrew Geissler { 47954daabe7SAndrew Geissler messages::internalError(asyncResp->res); 48054daabe7SAndrew Geissler return; 48154daabe7SAndrew Geissler } 48254daabe7SAndrew Geissler 48354daabe7SAndrew Geissler std::string formatDesc = 48454daabe7SAndrew Geissler swInvPurpose->substr(endDesc); 48554daabe7SAndrew Geissler asyncResp->res.jsonValue["Description"] = 48654daabe7SAndrew Geissler formatDesc + " update"; 487*87d84729SAndrew Geissler getRelatedItems(asyncResp, *swInvPurpose); 4886c4eb9deSJennifer Lee }, 489c711bf86SEd Tanous obj.second[0].first, obj.first, 490c711bf86SEd Tanous "org.freedesktop.DBus.Properties", "GetAll", 491c711bf86SEd Tanous "xyz.openbmc_project.Software.Version"); 4926c4eb9deSJennifer Lee } 493c711bf86SEd Tanous }, 494c711bf86SEd Tanous "xyz.openbmc_project.ObjectMapper", 495c711bf86SEd Tanous "/xyz/openbmc_project/object_mapper", 496c711bf86SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 497c711bf86SEd Tanous "/xyz/openbmc_project/software", int32_t(1), 4981abe55efSEd Tanous std::array<const char *, 1>{ 4991abe55efSEd Tanous "xyz.openbmc_project.Software.Version"}); 5006c4eb9deSJennifer Lee } 501729dae72SJennifer Lee }; 502729dae72SJennifer Lee 503729dae72SJennifer Lee } // namespace redfish 504