1 #include "inband_code_update.hpp" 2 3 #include "oem_ibm_handler.hpp" 4 #include "xyz/openbmc_project/Common/error.hpp" 5 6 #include <sdbusplus/server.hpp> 7 #include <xyz/openbmc_project/Dump/NewDump/server.hpp> 8 9 #include <exception> 10 11 namespace pldm 12 { 13 14 namespace responder 15 { 16 using namespace oem_ibm_platform; 17 18 std::string CodeUpdate::fetchCurrentBootSide() 19 { 20 return currBootSide; 21 } 22 23 std::string CodeUpdate::fetchNextBootSide() 24 { 25 return nextBootSide; 26 } 27 28 int CodeUpdate::setCurrentBootSide(const std::string& currSide) 29 { 30 currBootSide = currSide; 31 return PLDM_SUCCESS; 32 } 33 34 int CodeUpdate::setNextBootSide(const std::string& nextSide) 35 { 36 nextBootSide = nextSide; 37 std::string objPath{}; 38 if (nextBootSide == currBootSide) 39 { 40 objPath = runningVersion; 41 } 42 else 43 { 44 objPath = nonRunningVersion; 45 } 46 if (objPath.empty()) 47 { 48 std::cerr << "no nonRunningVersion present \n"; 49 return PLDM_PLATFORM_INVALID_STATE_VALUE; 50 } 51 52 pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority", 53 "uint8_t"}; 54 uint8_t val = 0; 55 pldm::utils::PropertyValue value = static_cast<uint8_t>(val); 56 try 57 { 58 dBusIntf->setDbusProperty(dbusMapping, value); 59 } 60 catch (const std::exception& e) 61 { 62 std::cerr << "failed to set the next boot side to " << objPath.c_str() 63 << " ERROR=" << e.what() << "\n"; 64 return PLDM_ERROR; 65 } 66 return PLDM_SUCCESS; 67 } 68 69 void CodeUpdate::setVersions() 70 { 71 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper"; 72 static constexpr auto functionalObjPath = 73 "/xyz/openbmc_project/software/functional"; 74 static constexpr auto activeObjPath = 75 "/xyz/openbmc_project/software/active"; 76 static constexpr auto propIntf = "org.freedesktop.DBus.Properties"; 77 78 auto& bus = dBusIntf->getBus(); 79 80 try 81 { 82 auto method = bus.new_method_call(mapperService, functionalObjPath, 83 propIntf, "Get"); 84 method.append("xyz.openbmc_project.Association", "endpoints"); 85 std::variant<std::vector<std::string>> paths; 86 87 auto reply = bus.call(method); 88 reply.read(paths); 89 90 runningVersion = std::get<std::vector<std::string>>(paths)[0]; 91 92 auto method1 = 93 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get"); 94 method1.append("xyz.openbmc_project.Association", "endpoints"); 95 96 auto reply1 = bus.call(method1); 97 reply1.read(paths); 98 for (const auto& path : std::get<std::vector<std::string>>(paths)) 99 { 100 if (path != runningVersion) 101 { 102 nonRunningVersion = path; 103 break; 104 } 105 } 106 } 107 catch (const std::exception& e) 108 { 109 std::cerr << "failed to make a d-bus call to Object Mapper " 110 "Association, ERROR=" 111 << e.what() << "\n"; 112 return; 113 } 114 115 using namespace sdbusplus::bus::match::rules; 116 captureNextBootSideChange.push_back( 117 std::make_unique<sdbusplus::bus::match::match>( 118 pldm::utils::DBusHandler::getBus(), 119 propertiesChanged(runningVersion, redundancyIntf), 120 [this](sdbusplus::message::message& msg) { 121 DbusChangedProps props; 122 std::string iface; 123 msg.read(iface, props); 124 processPriorityChangeNotification(props); 125 })); 126 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>( 127 pldm::utils::DBusHandler::getBus(), 128 "interface='org.freedesktop.DBus.ObjectManager',type='signal'," 129 "member='InterfacesAdded',path='/xyz/openbmc_project/software'", 130 [this](sdbusplus::message::message& msg) { 131 DBusInterfaceAdded interfaces; 132 sdbusplus::message::object_path path; 133 msg.read(path, interfaces); 134 for (auto& interface : interfaces) 135 { 136 if (interface.first == 137 "xyz.openbmc_project.Software.Activation") 138 { 139 newImageId = path.str; 140 break; 141 } 142 } 143 }); 144 } 145 146 void CodeUpdate::processPriorityChangeNotification( 147 const DbusChangedProps& chProperties) 148 { 149 static constexpr auto propName = "Priority"; 150 const auto it = chProperties.find(propName); 151 if (it == chProperties.end()) 152 { 153 return; 154 } 155 uint8_t newVal = std::get<uint8_t>(it->second); 156 nextBootSide = (newVal == 0) ? currBootSide 157 : ((currBootSide == Tside) ? Pside : Tside); 158 } 159 160 void CodeUpdate::setOemPlatformHandler( 161 pldm::responder::oem_platform::Handler* handler) 162 { 163 oemPlatformHandler = handler; 164 } 165 166 uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate) 167 { 168 uint8_t sensorOpState = tSideNum; 169 170 if (entityInstance == 0) 171 { 172 auto currSide = codeUpdate->fetchCurrentBootSide(); 173 if (currSide == Pside) 174 { 175 sensorOpState = pSideNum; 176 } 177 } 178 else if (entityInstance == 1) 179 { 180 auto nextSide = codeUpdate->fetchNextBootSide(); 181 if (nextSide == Pside) 182 { 183 sensorOpState = pSideNum; 184 } 185 } 186 else 187 { 188 sensorOpState = PLDM_SENSOR_UNKNOWN; 189 } 190 191 return sensorOpState; 192 } 193 194 int setBootSide(uint16_t entityInstance, uint8_t currState, 195 const std::vector<set_effecter_state_field>& stateField, 196 CodeUpdate* codeUpdate) 197 { 198 int rc = PLDM_SUCCESS; 199 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T"; 200 201 if (entityInstance == 0) 202 { 203 rc = codeUpdate->setCurrentBootSide(side); 204 } 205 else if (entityInstance == 1) 206 { 207 rc = codeUpdate->setNextBootSide(side); 208 } 209 else 210 { 211 rc = PLDM_PLATFORM_INVALID_STATE_VALUE; 212 } 213 return rc; 214 } 215 216 } // namespace responder 217 } // namespace pldm 218