blob: dab6316453a51b2e71acb2b2dec2d86721b22a9e [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
18#include <boost/asio/spawn.hpp>
19
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
27
Vernon Maueryba2c0832020-07-15 10:02:38 -070028#include <fstream>
29#include <regex>
30
31extern std::unique_ptr<boost::asio::steady_timer> timer;
32extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
33 srvMgrObjects;
34static bool updateInProgress = false;
35
36namespace phosphor
37{
38namespace service
39{
40
41static constexpr const char* overrideConfFileName = "override.conf";
42static constexpr const size_t restartTimeout = 15; // seconds
43
44static constexpr const char* systemd1UnitBasePath =
45 "/org/freedesktop/systemd1/unit/";
46static constexpr const char* systemdOverrideUnitBasePath =
47 "/etc/systemd/system/";
48
Chicago Duan25a0f632021-11-11 16:32:07 +080049#ifdef USB_CODE_UPDATE
50static constexpr const char* usbCodeUpdateStateFilePath =
51 "/var/lib/srvcfg_manager";
52static constexpr const char* usbCodeUpdateStateFile =
53 "/var/lib/srvcfg_manager/usb-code-update-state";
54static constexpr const char* emptyUsbCodeUpdateRulesFile =
55 "/etc/udev/rules.d/70-bmc-usb.rules";
56static constexpr const char* usbCodeUpdateObjectPath =
57 "/xyz/openbmc_project/control/service/phosphor_2dusb_2dcode_2dupdate";
58
59using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;
60
61void ServiceConfig::setUSBCodeUpdateState(const bool& state)
62{
63 // Enable usb code update
64 if (state)
65 {
66 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
67 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080068 lg2::info("Enable usb code update");
Chicago Duan25a0f632021-11-11 16:32:07 +080069 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
70 }
71 return;
72 }
73
74 // Disable usb code update
75 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
76 {
77 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
78 }
79 std::error_code ec;
80 std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
81 ec);
82 if (ec)
83 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080084 lg2::error("Disable usb code update failed");
Chicago Duan25a0f632021-11-11 16:32:07 +080085 return;
86 }
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080087 lg2::info("Disable usb code update");
Chicago Duan25a0f632021-11-11 16:32:07 +080088}
89
90void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
91 const bool& enabledState)
92{
93 if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
94 {
95 std::filesystem::create_directories(usbCodeUpdateStateFilePath);
96 }
97
98 UsbCodeUpdateStateMap usbCodeUpdateState;
99 usbCodeUpdateState[srvCfgPropMasked] = maskedState;
100 usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
101
102 std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
103 cereal::JSONOutputArchive archive(file);
104 archive(CEREAL_NVP(usbCodeUpdateState));
105}
106
107void ServiceConfig::getUSBCodeUpdateStateFromFile()
108{
109 if (!std::filesystem::exists(usbCodeUpdateStateFile))
110 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +0800111 lg2::info("usb-code-update-state file does not exist");
Chicago Duan25a0f632021-11-11 16:32:07 +0800112
113 unitMaskedState = false;
114 unitEnabledState = true;
115 unitRunningState = true;
116 setUSBCodeUpdateState(unitEnabledState);
117 return;
118 }
119
120 std::ifstream file(usbCodeUpdateStateFile);
121 cereal::JSONInputArchive archive(file);
122 UsbCodeUpdateStateMap usbCodeUpdateState;
123 archive(usbCodeUpdateState);
124
125 auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
126 if (iterMask != usbCodeUpdateState.end())
127 {
128 unitMaskedState = iterMask->second;
129 if (unitMaskedState)
130 {
131 unitEnabledState = !unitMaskedState;
132 unitRunningState = !unitMaskedState;
133 setUSBCodeUpdateState(unitEnabledState);
134 return;
135 }
136
137 auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
138 if (iterEnable != usbCodeUpdateState.end())
139 {
140 unitEnabledState = iterEnable->second;
141 unitRunningState = iterEnable->second;
142 setUSBCodeUpdateState(unitEnabledState);
143 }
144 }
145}
146#endif
147
Vernon Maueryba2c0832020-07-15 10:02:38 -0700148void ServiceConfig::updateSocketProperties(
149 const boost::container::flat_map<std::string, VariantType>& propertyMap)
150{
151 auto listenIt = propertyMap.find("Listen");
152 if (listenIt != propertyMap.end())
153 {
154 auto listenVal =
155 std::get<std::vector<std::tuple<std::string, std::string>>>(
156 listenIt->second);
157 if (listenVal.size())
158 {
159 protocol = std::get<0>(listenVal[0]);
160 std::string port = std::get<1>(listenVal[0]);
161 auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
162 nullptr, 10);
163 if (tmp > std::numeric_limits<uint16_t>::max())
164 {
165 throw std::out_of_range("Out of range");
166 }
167 portNum = tmp;
168 if (sockAttrIface && sockAttrIface->is_initialized())
169 {
170 internalSet = true;
171 sockAttrIface->set_property(sockAttrPropPort, portNum);
172 internalSet = false;
173 }
174 }
175 }
176}
177
178void ServiceConfig::updateServiceProperties(
179 const boost::container::flat_map<std::string, VariantType>& propertyMap)
180{
181 auto stateIt = propertyMap.find("UnitFileState");
182 if (stateIt != propertyMap.end())
183 {
184 stateValue = std::get<std::string>(stateIt->second);
185 unitEnabledState = unitMaskedState = false;
186 if (stateValue == stateMasked)
187 {
188 unitMaskedState = true;
189 }
190 else if (stateValue == stateEnabled)
191 {
192 unitEnabledState = true;
193 }
194 if (srvCfgIface && srvCfgIface->is_initialized())
195 {
196 internalSet = true;
197 srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
198 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
199 internalSet = false;
200 }
201 }
202 auto subStateIt = propertyMap.find("SubState");
203 if (subStateIt != propertyMap.end())
204 {
205 subStateValue = std::get<std::string>(subStateIt->second);
George Liua19b5092021-05-24 15:54:02 +0800206 if (subStateValue == subStateRunning ||
207 subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700208 {
209 unitRunningState = true;
210 }
211 if (srvCfgIface && srvCfgIface->is_initialized())
212 {
213 internalSet = true;
214 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
215 internalSet = false;
216 }
217 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800218
219#ifdef USB_CODE_UPDATE
220 if (objPath == usbCodeUpdateObjectPath)
221 {
222 getUSBCodeUpdateStateFromFile();
223 }
224#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700225}
226
227void ServiceConfig::queryAndUpdateProperties()
228{
George Liua19b5092021-05-24 15:54:02 +0800229 std::string objectPath =
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800230 isSocketActivatedService ? socketObjectPath : serviceObjectPath;
George Liua19b5092021-05-24 15:54:02 +0800231 if (objectPath.empty())
232 {
233 return;
234 }
235
Vernon Maueryba2c0832020-07-15 10:02:38 -0700236 conn->async_method_call(
237 [this](boost::system::error_code ec,
238 const boost::container::flat_map<std::string, VariantType>&
239 propertyMap) {
240 if (ec)
241 {
George Liucb267c82022-01-05 17:53:28 +0800242 lg2::error(
243 "async_method_call error: Failed to service unit properties: {EC}",
244 "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700245 return;
246 }
247 try
248 {
249 updateServiceProperties(propertyMap);
250 if (!socketObjectPath.empty())
251 {
252 conn->async_method_call(
253 [this](boost::system::error_code ec,
254 const boost::container::flat_map<
255 std::string, VariantType>& propertyMap) {
256 if (ec)
257 {
George Liucb267c82022-01-05 17:53:28 +0800258 lg2::error(
259 "async_method_call error: Failed to get all property: {EC}",
260 "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700261 return;
262 }
263 try
264 {
265 updateSocketProperties(propertyMap);
266 if (!srvCfgIface)
267 {
268 registerProperties();
269 }
270 }
271 catch (const std::exception& e)
272 {
George Liucb267c82022-01-05 17:53:28 +0800273 lg2::error(
274 "Exception in getting socket properties: {ERROR}",
275 "ERROR", e);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700276 return;
277 }
278 },
279 sysdService, socketObjectPath, dBusPropIntf,
280 dBusGetAllMethod, sysdSocketIntf);
281 }
282 else if (!srvCfgIface)
283 {
284 registerProperties();
285 }
286 }
287 catch (const std::exception& e)
288 {
George Liucb267c82022-01-05 17:53:28 +0800289 lg2::error("Exception in getting socket properties: {ERROR}",
290 "ERROR", e);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700291 return;
292 }
293 },
George Liua19b5092021-05-24 15:54:02 +0800294 sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700295 return;
296}
297
298void ServiceConfig::createSocketOverrideConf()
299{
300 if (!socketObjectPath.empty())
301 {
302 std::string socketUnitName(instantiatedUnitName + ".socket");
303 /// Check override socket directory exist, if not create it.
304 std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
305 ovrUnitFileDir += socketUnitName;
306 ovrUnitFileDir += ".d";
307 if (!std::filesystem::exists(ovrUnitFileDir))
308 {
309 if (!std::filesystem::create_directories(ovrUnitFileDir))
310 {
George Liucb267c82022-01-05 17:53:28 +0800311 lg2::error("Unable to create the {DIR} directory.", "DIR",
312 ovrUnitFileDir);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700313 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
314 Common::Error::InternalFailure>();
315 }
316 }
317 overrideConfDir = std::string(ovrUnitFileDir);
318 }
319}
320
321ServiceConfig::ServiceConfig(
322 sdbusplus::asio::object_server& srv_,
323 std::shared_ptr<sdbusplus::asio::connection>& conn_,
324 const std::string& objPath_, const std::string& baseUnitName_,
325 const std::string& instanceName_, const std::string& serviceObjPath_,
326 const std::string& socketObjPath_) :
327 conn(conn_),
328 server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
329 instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
330 socketObjectPath(socketObjPath_)
331{
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800332 isSocketActivatedService = serviceObjectPath.empty();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700333 instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
334 updatedFlag = 0;
335 queryAndUpdateProperties();
336 return;
337}
338
339std::string ServiceConfig::getSocketUnitName()
340{
341 return instantiatedUnitName + ".socket";
342}
343
344std::string ServiceConfig::getServiceUnitName()
345{
346 return instantiatedUnitName + ".service";
347}
348
349bool ServiceConfig::isMaskedOut()
350{
351 // return true if state is masked & no request to update the maskedState
352 return (
353 stateValue == "masked" &&
354 !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
355}
356
357void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
358{
359 if (!updatedFlag || isMaskedOut())
360 {
361 // No updates / masked - Just return.
362 return;
363 }
George Liucb267c82022-01-05 17:53:28 +0800364 lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
George Liua19b5092021-05-24 15:54:02 +0800365 if (subStateValue == subStateRunning || subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700366 {
367 if (!socketObjectPath.empty())
368 {
369 systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
370 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800371 if (!isSocketActivatedService)
George Liua19b5092021-05-24 15:54:02 +0800372 {
373 systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
374 }
375 else
376 {
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800377 // For socket-activated service, each connection will spawn a
378 // service instance from template. Need to find all spawned service
379 // `<unitName>@<attribute>.service` and stop them through the
380 // systemdUnitAction method
George Liua19b5092021-05-24 15:54:02 +0800381 boost::system::error_code ec;
382 auto listUnits =
383 conn->yield_method_call<std::vector<ListUnitsType>>(
384 yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
385 "ListUnits");
386
387 checkAndThrowInternalFailure(
388 ec, "yield_method_call error: ListUnits failed");
389
390 for (const auto& unit : listUnits)
391 {
392 const auto& service =
393 std::get<static_cast<int>(ListUnitElements::name)>(unit);
394 const auto& status =
395 std::get<static_cast<int>(ListUnitElements::subState)>(
396 unit);
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800397 if (service.find(baseUnitName + "@") != std::string::npos &&
George Liua19b5092021-05-24 15:54:02 +0800398 service.find(".service") != std::string::npos &&
399 status == subStateRunning)
400 {
401 systemdUnitAction(conn, yield, service, sysdStopUnit);
402 }
403 }
404 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700405 }
406
407 if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
408 {
409 createSocketOverrideConf();
410 // Create override config file and write data.
411 std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
412 std::string tmpFile{ovrCfgFile + "_tmp"};
413 std::ofstream cfgFile(tmpFile, std::ios::out);
414 if (!cfgFile.good())
415 {
George Liucb267c82022-01-05 17:53:28 +0800416 lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
417 tmpFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700418 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
419 Error::InternalFailure>();
420 }
421
422 // Write the socket header
423 cfgFile << "[Socket]\n";
424 // Listen
425 cfgFile << "Listen" << protocol << "="
426 << "\n";
427 cfgFile << "Listen" << protocol << "=" << portNum << "\n";
428 cfgFile.close();
429
430 if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
431 {
George Liucb267c82022-01-05 17:53:28 +0800432 lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
433 "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700434 std::remove(tmpFile.c_str());
435 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
436 Error::InternalFailure>();
437 }
438 }
439
440 if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
441 (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
442 {
443 std::vector<std::string> unitFiles;
444 if (socketObjectPath.empty())
445 {
446 unitFiles = {getServiceUnitName()};
447 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800448 else if (serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800449 {
450 unitFiles = {getSocketUnitName()};
451 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700452 else
453 {
454 unitFiles = {getSocketUnitName(), getServiceUnitName()};
455 }
456 systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
457 unitMaskedState, unitEnabledState);
458 }
459 return;
460}
461void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
462{
463 if (!updatedFlag || isMaskedOut())
464 {
465 // No updates. Just return.
466 return;
467 }
468
469 if (unitRunningState)
470 {
471 if (!socketObjectPath.empty())
472 {
473 systemdUnitAction(conn, yield, getSocketUnitName(),
474 sysdRestartUnit);
475 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800476 if (!serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800477 {
478 systemdUnitAction(conn, yield, getServiceUnitName(),
479 sysdRestartUnit);
480 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700481 }
482
483 // Reset the flag
484 updatedFlag = 0;
485
George Liucb267c82022-01-05 17:53:28 +0800486 lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700487
488 queryAndUpdateProperties();
489 return;
490}
491
492void ServiceConfig::startServiceRestartTimer()
493{
494 timer->expires_after(std::chrono::seconds(restartTimeout));
495 timer->async_wait([this](const boost::system::error_code& ec) {
496 if (ec == boost::asio::error::operation_aborted)
497 {
498 // Timer reset.
499 return;
500 }
501 else if (ec)
502 {
George Liucb267c82022-01-05 17:53:28 +0800503 lg2::error("async wait error: {EC}", "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700504 return;
505 }
506 updateInProgress = true;
507 boost::asio::spawn(conn->get_io_context(),
508 [this](boost::asio::yield_context yield) {
509 // Stop and apply configuration for all objects
510 for (auto& srvMgrObj : srvMgrObjects)
511 {
512 auto& srvObj = srvMgrObj.second;
513 if (srvObj->updatedFlag)
514 {
515 srvObj->stopAndApplyUnitConfig(yield);
516 }
517 }
518 // Do system reload
519 systemdDaemonReload(conn, yield);
520 // restart unit config.
521 for (auto& srvMgrObj : srvMgrObjects)
522 {
523 auto& srvObj = srvMgrObj.second;
524 if (srvObj->updatedFlag)
525 {
526 srvObj->restartUnitConfig(yield);
527 }
528 }
529 updateInProgress = false;
530 });
531 });
532}
533
534void ServiceConfig::registerProperties()
535{
536 srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
537
538 if (!socketObjectPath.empty())
539 {
540 sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
541 sockAttrIface->register_property(
542 sockAttrPropPort, portNum,
543 [this](const uint16_t& req, uint16_t& res) {
544 if (!internalSet)
545 {
546 if (req == res)
547 {
548 return 1;
549 }
550 if (updateInProgress)
551 {
552 return 0;
553 }
554 portNum = req;
555 updatedFlag |=
556 (1 << static_cast<uint8_t>(UpdatedProp::port));
557 startServiceRestartTimer();
558 }
559 res = req;
560 return 1;
561 });
562 }
563
564 srvCfgIface->register_property(
565 srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
566 if (!internalSet)
567 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800568#ifdef USB_CODE_UPDATE
569 if (objPath == usbCodeUpdateObjectPath)
570 {
571 unitMaskedState = req;
572 unitEnabledState = !unitMaskedState;
573 unitRunningState = !unitMaskedState;
574 internalSet = true;
575 srvCfgIface->set_property(srvCfgPropEnabled,
576 unitEnabledState);
577 srvCfgIface->set_property(srvCfgPropRunning,
578 unitRunningState);
579 srvCfgIface->set_property(srvCfgPropMasked,
580 unitMaskedState);
581 internalSet = false;
582 setUSBCodeUpdateState(unitEnabledState);
583 saveUSBCodeUpdateStateToFile(unitMaskedState,
584 unitEnabledState);
585 return 1;
586 }
587#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700588 if (req == res)
589 {
590 return 1;
591 }
592 if (updateInProgress)
593 {
594 return 0;
595 }
596 unitMaskedState = req;
597 unitEnabledState = !unitMaskedState;
598 unitRunningState = !unitMaskedState;
599 updatedFlag |=
600 (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
601 (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
602 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
603 internalSet = true;
604 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
605 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
606 internalSet = false;
607 startServiceRestartTimer();
608 }
609 res = req;
610 return 1;
611 });
612
613 srvCfgIface->register_property(
614 srvCfgPropEnabled, unitEnabledState,
615 [this](const bool& req, bool& res) {
616 if (!internalSet)
617 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800618#ifdef USB_CODE_UPDATE
619 if (objPath == usbCodeUpdateObjectPath)
620 {
621 if (unitMaskedState)
622 { // block updating if masked
Jiaqing Zhaof27f4312022-04-02 17:42:46 +0800623 lg2::error("Invalid value specified");
Chicago Duan25a0f632021-11-11 16:32:07 +0800624 return -EINVAL;
625 }
626 unitEnabledState = req;
627 unitRunningState = req;
628 internalSet = true;
629 srvCfgIface->set_property(srvCfgPropEnabled,
630 unitEnabledState);
631 srvCfgIface->set_property(srvCfgPropRunning,
632 unitRunningState);
633 internalSet = false;
634 setUSBCodeUpdateState(unitEnabledState);
635 saveUSBCodeUpdateStateToFile(unitMaskedState,
636 unitEnabledState);
637 res = req;
638 return 1;
639 }
640#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700641 if (req == res)
642 {
643 return 1;
644 }
645 if (updateInProgress)
646 {
647 return 0;
648 }
649 if (unitMaskedState)
650 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800651 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700652 return -EINVAL;
653 }
654 unitEnabledState = req;
655 updatedFlag |=
656 (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
657 startServiceRestartTimer();
658 }
659 res = req;
660 return 1;
661 });
662
663 srvCfgIface->register_property(
664 srvCfgPropRunning, unitRunningState,
665 [this](const bool& req, bool& res) {
666 if (!internalSet)
667 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800668#ifdef USB_CODE_UPDATE
669 if (objPath == usbCodeUpdateObjectPath)
670 {
671 if (unitMaskedState)
672 { // block updating if masked
Jiaqing Zhaof27f4312022-04-02 17:42:46 +0800673 lg2::error("Invalid value specified");
Chicago Duan25a0f632021-11-11 16:32:07 +0800674 return -EINVAL;
675 }
676 unitEnabledState = req;
677 unitRunningState = req;
678 internalSet = true;
679 srvCfgIface->set_property(srvCfgPropEnabled,
680 unitEnabledState);
681 srvCfgIface->set_property(srvCfgPropRunning,
682 unitRunningState);
683 internalSet = false;
684 setUSBCodeUpdateState(unitEnabledState);
685 saveUSBCodeUpdateStateToFile(unitMaskedState,
686 unitEnabledState);
687 res = req;
688 return 1;
689 }
690#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700691 if (req == res)
692 {
693 return 1;
694 }
695 if (updateInProgress)
696 {
697 return 0;
698 }
699 if (unitMaskedState)
700 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800701 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700702 return -EINVAL;
703 }
704 unitRunningState = req;
705 updatedFlag |=
706 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
707 startServiceRestartTimer();
708 }
709 res = req;
710 return 1;
711 });
712
713 srvCfgIface->initialize();
714 if (!socketObjectPath.empty())
715 {
716 sockAttrIface->initialize();
717 }
718 return;
719}
720
721} // namespace service
722} // namespace phosphor