blob: a7cb90c290f9dc283c9a47ed6f14c3905b4a4d73 [file] [log] [blame]
Vernon Maueryba2c0832020-07-15 10:02:38 -07001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#include "srvcfg_manager.hpp"
17
Ed Tanousc828db72025-04-01 16:42:24 -070018#include <boost/asio/detached.hpp>
Vernon Maueryba2c0832020-07-15 10:02:38 -070019#include <boost/asio/spawn.hpp>
Chicago Duan25a0f632021-11-11 16:32:07 +080020#ifdef USB_CODE_UPDATE
21#include <cereal/archives/json.hpp>
22#include <cereal/types/tuple.hpp>
23#include <cereal/types/unordered_map.hpp>
24
25#include <cstdio>
26#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -070027#include <fstream>
Andrew Geisslercb0f1342025-04-22 16:08:27 -050028#ifdef PERSIST_SETTINGS
29#include <nlohmann/json.hpp>
30#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -070031#include <regex>
32
33extern std::unique_ptr<boost::asio::steady_timer> timer;
34extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
35 srvMgrObjects;
36static bool updateInProgress = false;
37
38namespace phosphor
39{
40namespace service
41{
42
43static constexpr const char* overrideConfFileName = "override.conf";
44static constexpr const size_t restartTimeout = 15; // seconds
45
46static constexpr const char* systemd1UnitBasePath =
47 "/org/freedesktop/systemd1/unit/";
48static constexpr const char* systemdOverrideUnitBasePath =
49 "/etc/systemd/system/";
50
Andrew Geisslercb0f1342025-04-22 16:08:27 -050051#ifdef PERSIST_SETTINGS
52static constexpr const char* persistDataFileVersionStr = "Version";
53static constexpr const size_t persistDataFileVersion = 1;
54#endif
55
Chicago Duan25a0f632021-11-11 16:32:07 +080056#ifdef USB_CODE_UPDATE
57static constexpr const char* usbCodeUpdateStateFilePath =
58 "/var/lib/srvcfg_manager";
59static constexpr const char* usbCodeUpdateStateFile =
60 "/var/lib/srvcfg_manager/usb-code-update-state";
61static constexpr const char* emptyUsbCodeUpdateRulesFile =
62 "/etc/udev/rules.d/70-bmc-usb.rules";
Chicago Duan25a0f632021-11-11 16:32:07 +080063
64using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;
65
66void ServiceConfig::setUSBCodeUpdateState(const bool& state)
67{
68 // Enable usb code update
69 if (state)
70 {
71 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
72 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080073 lg2::info("Enable usb code update");
Chicago Duan25a0f632021-11-11 16:32:07 +080074 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
75 }
76 return;
77 }
78
79 // Disable usb code update
80 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
81 {
82 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
83 }
84 std::error_code ec;
85 std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
86 ec);
87 if (ec)
88 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080089 lg2::error("Disable usb code update failed");
Chicago Duan25a0f632021-11-11 16:32:07 +080090 return;
91 }
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080092 lg2::info("Disable usb code update");
Chicago Duan25a0f632021-11-11 16:32:07 +080093}
94
95void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
96 const bool& enabledState)
97{
98 if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
99 {
100 std::filesystem::create_directories(usbCodeUpdateStateFilePath);
101 }
102
103 UsbCodeUpdateStateMap usbCodeUpdateState;
104 usbCodeUpdateState[srvCfgPropMasked] = maskedState;
105 usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
106
107 std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
108 cereal::JSONOutputArchive archive(file);
109 archive(CEREAL_NVP(usbCodeUpdateState));
110}
111
112void ServiceConfig::getUSBCodeUpdateStateFromFile()
113{
114 if (!std::filesystem::exists(usbCodeUpdateStateFile))
115 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +0800116 lg2::info("usb-code-update-state file does not exist");
Chicago Duan25a0f632021-11-11 16:32:07 +0800117
118 unitMaskedState = false;
119 unitEnabledState = true;
120 unitRunningState = true;
121 setUSBCodeUpdateState(unitEnabledState);
122 return;
123 }
124
125 std::ifstream file(usbCodeUpdateStateFile);
126 cereal::JSONInputArchive archive(file);
127 UsbCodeUpdateStateMap usbCodeUpdateState;
128 archive(usbCodeUpdateState);
129
130 auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
131 if (iterMask != usbCodeUpdateState.end())
132 {
133 unitMaskedState = iterMask->second;
134 if (unitMaskedState)
135 {
136 unitEnabledState = !unitMaskedState;
137 unitRunningState = !unitMaskedState;
138 setUSBCodeUpdateState(unitEnabledState);
139 return;
140 }
141
142 auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
143 if (iterEnable != usbCodeUpdateState.end())
144 {
145 unitEnabledState = iterEnable->second;
146 unitRunningState = iterEnable->second;
147 setUSBCodeUpdateState(unitEnabledState);
148 }
149 }
150}
151#endif
152
Vernon Maueryba2c0832020-07-15 10:02:38 -0700153void ServiceConfig::updateSocketProperties(
154 const boost::container::flat_map<std::string, VariantType>& propertyMap)
155{
156 auto listenIt = propertyMap.find("Listen");
157 if (listenIt != propertyMap.end())
158 {
159 auto listenVal =
160 std::get<std::vector<std::tuple<std::string, std::string>>>(
161 listenIt->second);
162 if (listenVal.size())
163 {
164 protocol = std::get<0>(listenVal[0]);
165 std::string port = std::get<1>(listenVal[0]);
166 auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
167 nullptr, 10);
168 if (tmp > std::numeric_limits<uint16_t>::max())
169 {
170 throw std::out_of_range("Out of range");
171 }
172 portNum = tmp;
173 if (sockAttrIface && sockAttrIface->is_initialized())
174 {
175 internalSet = true;
176 sockAttrIface->set_property(sockAttrPropPort, portNum);
177 internalSet = false;
178 }
179 }
180 }
181}
182
183void ServiceConfig::updateServiceProperties(
184 const boost::container::flat_map<std::string, VariantType>& propertyMap)
185{
186 auto stateIt = propertyMap.find("UnitFileState");
187 if (stateIt != propertyMap.end())
188 {
189 stateValue = std::get<std::string>(stateIt->second);
190 unitEnabledState = unitMaskedState = false;
191 if (stateValue == stateMasked)
192 {
193 unitMaskedState = true;
194 }
195 else if (stateValue == stateEnabled)
196 {
197 unitEnabledState = true;
198 }
199 if (srvCfgIface && srvCfgIface->is_initialized())
200 {
201 internalSet = true;
202 srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
203 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
204 internalSet = false;
205 }
206 }
207 auto subStateIt = propertyMap.find("SubState");
208 if (subStateIt != propertyMap.end())
209 {
210 subStateValue = std::get<std::string>(subStateIt->second);
George Liua19b5092021-05-24 15:54:02 +0800211 if (subStateValue == subStateRunning ||
212 subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700213 {
214 unitRunningState = true;
215 }
216 if (srvCfgIface && srvCfgIface->is_initialized())
217 {
218 internalSet = true;
219 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
220 internalSet = false;
221 }
222 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800223
224#ifdef USB_CODE_UPDATE
Jiaqing Zhao430d7ea2022-04-01 23:23:25 +0800225 if (baseUnitName == usbCodeUpdateUnitName)
Chicago Duan25a0f632021-11-11 16:32:07 +0800226 {
227 getUSBCodeUpdateStateFromFile();
228 }
229#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700230}
231
232void ServiceConfig::queryAndUpdateProperties()
233{
Patrick Williamsde879722024-08-16 15:21:46 -0400234 std::string objectPath =
235 isSocketActivatedService ? socketObjectPath : serviceObjectPath;
George Liua19b5092021-05-24 15:54:02 +0800236 if (objectPath.empty())
237 {
238 return;
239 }
240
Vernon Maueryba2c0832020-07-15 10:02:38 -0700241 conn->async_method_call(
242 [this](boost::system::error_code ec,
243 const boost::container::flat_map<std::string, VariantType>&
244 propertyMap) {
Patrick Williamsde879722024-08-16 15:21:46 -0400245 if (ec)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700246 {
Patrick Williamsde879722024-08-16 15:21:46 -0400247 lg2::error(
248 "async_method_call error: Failed to service unit properties: {EC}",
249 "EC", ec.value());
250 return;
Vernon Maueryba2c0832020-07-15 10:02:38 -0700251 }
Patrick Williamsde879722024-08-16 15:21:46 -0400252 try
Vernon Maueryba2c0832020-07-15 10:02:38 -0700253 {
Patrick Williamsde879722024-08-16 15:21:46 -0400254 updateServiceProperties(propertyMap);
255 if (!socketObjectPath.empty())
256 {
257 conn->async_method_call(
258 [this](boost::system::error_code ec,
259 const boost::container::flat_map<
260 std::string, VariantType>& propertyMap) {
261 if (ec)
262 {
263 lg2::error(
264 "async_method_call error: Failed to get all property: {EC}",
265 "EC", ec.value());
266 return;
267 }
268 try
269 {
270 updateSocketProperties(propertyMap);
271 if (!srvCfgIface)
272 {
273 registerProperties();
274 }
275 }
276 catch (const std::exception& e)
277 {
278 lg2::error(
279 "Exception in getting socket properties: {ERROR}",
280 "ERROR", e);
281 return;
282 }
283 },
284 sysdService, socketObjectPath, dBusPropIntf,
285 dBusGetAllMethod, sysdSocketIntf);
286 }
287 else if (!srvCfgIface)
288 {
289 registerProperties();
290 }
Andrew Geisslercb0f1342025-04-22 16:08:27 -0500291 writeStateFile();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700292 }
Patrick Williamsde879722024-08-16 15:21:46 -0400293 catch (const std::exception& e)
294 {
295 lg2::error("Exception in getting socket properties: {ERROR}",
296 "ERROR", e);
297 return;
298 }
299 },
George Liua19b5092021-05-24 15:54:02 +0800300 sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700301 return;
302}
303
304void ServiceConfig::createSocketOverrideConf()
305{
306 if (!socketObjectPath.empty())
307 {
308 std::string socketUnitName(instantiatedUnitName + ".socket");
309 /// Check override socket directory exist, if not create it.
310 std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
311 ovrUnitFileDir += socketUnitName;
312 ovrUnitFileDir += ".d";
313 if (!std::filesystem::exists(ovrUnitFileDir))
314 {
315 if (!std::filesystem::create_directories(ovrUnitFileDir))
316 {
George Liucb267c82022-01-05 17:53:28 +0800317 lg2::error("Unable to create the {DIR} directory.", "DIR",
318 ovrUnitFileDir);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700319 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
320 Common::Error::InternalFailure>();
321 }
322 }
323 overrideConfDir = std::string(ovrUnitFileDir);
324 }
325}
326
Andrew Geisslercb0f1342025-04-22 16:08:27 -0500327void ServiceConfig::writeStateFile()
328{
329#ifdef PERSIST_SETTINGS
330 nlohmann::json stateMap;
331 stateMap[persistDataFileVersionStr] = persistDataFileVersion;
332 stateMap[srvCfgPropMasked] = unitMaskedState;
333 stateMap[srvCfgPropEnabled] = unitEnabledState;
334 stateMap[srvCfgPropRunning] = unitRunningState;
335
336 std::ofstream file(stateFile);
337 file << stateMap;
338 file.close();
339#endif
340}
341
Vernon Maueryba2c0832020-07-15 10:02:38 -0700342ServiceConfig::ServiceConfig(
343 sdbusplus::asio::object_server& srv_,
344 std::shared_ptr<sdbusplus::asio::connection>& conn_,
345 const std::string& objPath_, const std::string& baseUnitName_,
346 const std::string& instanceName_, const std::string& serviceObjPath_,
347 const std::string& socketObjPath_) :
Patrick Williamsde879722024-08-16 15:21:46 -0400348 conn(conn_), server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
Vernon Maueryba2c0832020-07-15 10:02:38 -0700349 instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
350 socketObjectPath(socketObjPath_)
351{
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800352 isSocketActivatedService = serviceObjectPath.empty();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700353 instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
354 updatedFlag = 0;
Andrew Geisslercb0f1342025-04-22 16:08:27 -0500355 stateFile = srvDataBaseDir + instantiatedUnitName;
Vernon Maueryba2c0832020-07-15 10:02:38 -0700356 queryAndUpdateProperties();
357 return;
358}
359
360std::string ServiceConfig::getSocketUnitName()
361{
362 return instantiatedUnitName + ".socket";
363}
364
365std::string ServiceConfig::getServiceUnitName()
366{
367 return instantiatedUnitName + ".service";
368}
369
370bool ServiceConfig::isMaskedOut()
371{
372 // return true if state is masked & no request to update the maskedState
373 return (
374 stateValue == "masked" &&
375 !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
376}
377
378void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
379{
380 if (!updatedFlag || isMaskedOut())
381 {
382 // No updates / masked - Just return.
383 return;
384 }
George Liucb267c82022-01-05 17:53:28 +0800385 lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
George Liua19b5092021-05-24 15:54:02 +0800386 if (subStateValue == subStateRunning || subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700387 {
388 if (!socketObjectPath.empty())
389 {
390 systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
391 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800392 if (!isSocketActivatedService)
George Liua19b5092021-05-24 15:54:02 +0800393 {
394 systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
395 }
396 else
397 {
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800398 // For socket-activated service, each connection will spawn a
399 // service instance from template. Need to find all spawned service
400 // `<unitName>@<attribute>.service` and stop them through the
401 // systemdUnitAction method
George Liua19b5092021-05-24 15:54:02 +0800402 boost::system::error_code ec;
403 auto listUnits =
404 conn->yield_method_call<std::vector<ListUnitsType>>(
405 yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
406 "ListUnits");
407
408 checkAndThrowInternalFailure(
409 ec, "yield_method_call error: ListUnits failed");
410
411 for (const auto& unit : listUnits)
412 {
413 const auto& service =
414 std::get<static_cast<int>(ListUnitElements::name)>(unit);
415 const auto& status =
416 std::get<static_cast<int>(ListUnitElements::subState)>(
417 unit);
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800418 if (service.find(baseUnitName + "@") != std::string::npos &&
George Liua19b5092021-05-24 15:54:02 +0800419 service.find(".service") != std::string::npos &&
420 status == subStateRunning)
421 {
422 systemdUnitAction(conn, yield, service, sysdStopUnit);
423 }
424 }
425 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700426 }
427
428 if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
429 {
430 createSocketOverrideConf();
431 // Create override config file and write data.
432 std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
433 std::string tmpFile{ovrCfgFile + "_tmp"};
434 std::ofstream cfgFile(tmpFile, std::ios::out);
435 if (!cfgFile.good())
436 {
George Liucb267c82022-01-05 17:53:28 +0800437 lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
438 tmpFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700439 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
440 Error::InternalFailure>();
441 }
442
443 // Write the socket header
444 cfgFile << "[Socket]\n";
445 // Listen
446 cfgFile << "Listen" << protocol << "="
447 << "\n";
448 cfgFile << "Listen" << protocol << "=" << portNum << "\n";
449 cfgFile.close();
450
451 if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
452 {
George Liucb267c82022-01-05 17:53:28 +0800453 lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
454 "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700455 std::remove(tmpFile.c_str());
456 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
457 Error::InternalFailure>();
458 }
459 }
460
461 if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
462 (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
463 {
464 std::vector<std::string> unitFiles;
465 if (socketObjectPath.empty())
466 {
467 unitFiles = {getServiceUnitName()};
468 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800469 else if (serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800470 {
471 unitFiles = {getSocketUnitName()};
472 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700473 else
474 {
475 unitFiles = {getSocketUnitName(), getServiceUnitName()};
476 }
477 systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
478 unitMaskedState, unitEnabledState);
479 }
480 return;
481}
482void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
483{
484 if (!updatedFlag || isMaskedOut())
485 {
486 // No updates. Just return.
487 return;
488 }
489
490 if (unitRunningState)
491 {
492 if (!socketObjectPath.empty())
493 {
494 systemdUnitAction(conn, yield, getSocketUnitName(),
495 sysdRestartUnit);
496 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800497 if (!serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800498 {
499 systemdUnitAction(conn, yield, getServiceUnitName(),
500 sysdRestartUnit);
501 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700502 }
503
504 // Reset the flag
505 updatedFlag = 0;
506
George Liucb267c82022-01-05 17:53:28 +0800507 lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700508
509 queryAndUpdateProperties();
510 return;
511}
512
513void ServiceConfig::startServiceRestartTimer()
514{
515 timer->expires_after(std::chrono::seconds(restartTimeout));
516 timer->async_wait([this](const boost::system::error_code& ec) {
517 if (ec == boost::asio::error::operation_aborted)
518 {
519 // Timer reset.
520 return;
521 }
522 else if (ec)
523 {
George Liucb267c82022-01-05 17:53:28 +0800524 lg2::error("async wait error: {EC}", "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700525 return;
526 }
527 updateInProgress = true;
Andrew Geisslercb0f1342025-04-22 16:08:27 -0500528 // Ensure our persistent files are updated with changes
529 writeStateFile();
Ed Tanousc828db72025-04-01 16:42:24 -0700530 boost::asio::spawn(
Jason M. Bills543e0722025-02-26 10:33:58 -0800531 conn->get_io_context(),
532 [this](boost::asio::yield_context yield) {
533 // Stop and apply configuration for all objects
534 for (auto& srvMgrObj : srvMgrObjects)
535 {
536 auto& srvObj = srvMgrObj.second;
537 if (srvObj->updatedFlag)
538 {
539 srvObj->stopAndApplyUnitConfig(yield);
540 }
541 }
542 // Do system reload
543 systemdDaemonReload(conn, yield);
544 // restart unit config.
545 for (auto& srvMgrObj : srvMgrObjects)
546 {
547 auto& srvObj = srvMgrObj.second;
548 if (srvObj->updatedFlag)
549 {
550 srvObj->restartUnitConfig(yield);
551 }
552 }
553 updateInProgress = false;
554 },
Ed Tanousc828db72025-04-01 16:42:24 -0700555 boost::asio::detached);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700556 });
557}
558
559void ServiceConfig::registerProperties()
560{
561 srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
562
563 if (!socketObjectPath.empty())
564 {
565 sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
566 sockAttrIface->register_property(
567 sockAttrPropPort, portNum,
568 [this](const uint16_t& req, uint16_t& res) {
Patrick Williamsde879722024-08-16 15:21:46 -0400569 if (!internalSet)
570 {
571 if (req == res)
572 {
573 return 1;
574 }
575 if (updateInProgress)
576 {
577 return 0;
578 }
579 portNum = req;
580 updatedFlag |=
581 (1 << static_cast<uint8_t>(UpdatedProp::port));
582 startServiceRestartTimer();
583 }
584 res = req;
585 return 1;
586 });
587 }
588
589 srvCfgIface->register_property(
590 srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
Vernon Maueryba2c0832020-07-15 10:02:38 -0700591 if (!internalSet)
592 {
Patrick Williamsde879722024-08-16 15:21:46 -0400593#ifdef USB_CODE_UPDATE
594 if (baseUnitName == usbCodeUpdateUnitName)
595 {
596 unitMaskedState = req;
597 unitEnabledState = !unitMaskedState;
598 unitRunningState = !unitMaskedState;
599 internalSet = true;
600 srvCfgIface->set_property(srvCfgPropEnabled,
601 unitEnabledState);
602 srvCfgIface->set_property(srvCfgPropRunning,
603 unitRunningState);
604 srvCfgIface->set_property(srvCfgPropMasked,
605 unitMaskedState);
606 internalSet = false;
607 setUSBCodeUpdateState(unitEnabledState);
608 saveUSBCodeUpdateStateToFile(unitMaskedState,
609 unitEnabledState);
610 return 1;
611 }
612#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700613 if (req == res)
614 {
615 return 1;
616 }
617 if (updateInProgress)
618 {
619 return 0;
620 }
Patrick Williamsde879722024-08-16 15:21:46 -0400621 unitMaskedState = req;
622 unitEnabledState = !unitMaskedState;
623 unitRunningState = !unitMaskedState;
624 updatedFlag |=
625 (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
626 (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
627 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
628 internalSet = true;
629 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
630 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
631 internalSet = false;
Vernon Maueryba2c0832020-07-15 10:02:38 -0700632 startServiceRestartTimer();
633 }
634 res = req;
635 return 1;
Patrick Williamsd8effd62023-10-20 11:19:46 -0500636 });
Vernon Maueryba2c0832020-07-15 10:02:38 -0700637
Patrick Williamsde879722024-08-16 15:21:46 -0400638 srvCfgIface->register_property(
639 srvCfgPropEnabled, unitEnabledState,
640 [this](const bool& req, bool& res) {
641 if (!internalSet)
Patrick Williamsdfc72702023-05-10 07:51:18 -0500642 {
Patrick Williamsde879722024-08-16 15:21:46 -0400643#ifdef USB_CODE_UPDATE
644 if (baseUnitName == usbCodeUpdateUnitName)
645 {
646 if (unitMaskedState)
647 { // block updating if masked
648 lg2::error("Invalid value specified");
649 return -EINVAL;
650 }
651 unitEnabledState = req;
652 unitRunningState = req;
653 internalSet = true;
654 srvCfgIface->set_property(srvCfgPropEnabled,
655 unitEnabledState);
656 srvCfgIface->set_property(srvCfgPropRunning,
657 unitRunningState);
658 internalSet = false;
659 setUSBCodeUpdateState(unitEnabledState);
660 saveUSBCodeUpdateStateToFile(unitMaskedState,
661 unitEnabledState);
662 res = req;
663 return 1;
664 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800665#endif
Patrick Williamsde879722024-08-16 15:21:46 -0400666 if (req == res)
667 {
668 return 1;
669 }
670 if (updateInProgress)
671 {
672 return 0;
673 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700674 if (unitMaskedState)
675 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800676 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700677 return -EINVAL;
678 }
679 unitEnabledState = req;
Patrick Williamsde879722024-08-16 15:21:46 -0400680 updatedFlag |=
681 (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
682 startServiceRestartTimer();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700683 }
Patrick Williamsde879722024-08-16 15:21:46 -0400684 res = req;
685 return 1;
686 });
Patrick Williamsdfc72702023-05-10 07:51:18 -0500687
Patrick Williamsde879722024-08-16 15:21:46 -0400688 srvCfgIface->register_property(
689 srvCfgPropRunning, unitRunningState,
690 [this](const bool& req, bool& res) {
691 if (!internalSet)
Patrick Williamsdfc72702023-05-10 07:51:18 -0500692 {
Patrick Williamsde879722024-08-16 15:21:46 -0400693#ifdef USB_CODE_UPDATE
694 if (baseUnitName == usbCodeUpdateUnitName)
695 {
696 if (unitMaskedState)
697 { // block updating if masked
698 lg2::error("Invalid value specified");
699 return -EINVAL;
700 }
701 unitEnabledState = req;
702 unitRunningState = req;
703 internalSet = true;
704 srvCfgIface->set_property(srvCfgPropEnabled,
705 unitEnabledState);
706 srvCfgIface->set_property(srvCfgPropRunning,
707 unitRunningState);
708 internalSet = false;
709 setUSBCodeUpdateState(unitEnabledState);
710 saveUSBCodeUpdateStateToFile(unitMaskedState,
711 unitEnabledState);
712 res = req;
713 return 1;
714 }
715#endif
716 if (req == res)
717 {
718 return 1;
719 }
720 if (updateInProgress)
721 {
722 return 0;
723 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700724 if (unitMaskedState)
725 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800726 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700727 return -EINVAL;
728 }
729 unitRunningState = req;
Patrick Williamsde879722024-08-16 15:21:46 -0400730 updatedFlag |=
731 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
732 startServiceRestartTimer();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700733 }
Patrick Williamsde879722024-08-16 15:21:46 -0400734 res = req;
735 return 1;
736 });
Vernon Maueryba2c0832020-07-15 10:02:38 -0700737
738 srvCfgIface->initialize();
739 if (!socketObjectPath.empty())
740 {
741 sockAttrIface->initialize();
742 }
743 return;
744}
745
746} // namespace service
747} // namespace phosphor