blob: 9840cc43ccb620a13ecc56140b012e2021c0d3be [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 {
68 phosphor::logging::log<phosphor::logging::level::INFO>(
69 "Enable usb code update");
70 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
71 }
72 return;
73 }
74
75 // Disable usb code update
76 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
77 {
78 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
79 }
80 std::error_code ec;
81 std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
82 ec);
83 if (ec)
84 {
85 phosphor::logging::log<phosphor::logging::level::ERR>(
86 "Disable usb code update failed");
87 return;
88 }
89 phosphor::logging::log<phosphor::logging::level::INFO>(
90 "Disable usb code update");
91}
92
93void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
94 const bool& enabledState)
95{
96 if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
97 {
98 std::filesystem::create_directories(usbCodeUpdateStateFilePath);
99 }
100
101 UsbCodeUpdateStateMap usbCodeUpdateState;
102 usbCodeUpdateState[srvCfgPropMasked] = maskedState;
103 usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
104
105 std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
106 cereal::JSONOutputArchive archive(file);
107 archive(CEREAL_NVP(usbCodeUpdateState));
108}
109
110void ServiceConfig::getUSBCodeUpdateStateFromFile()
111{
112 if (!std::filesystem::exists(usbCodeUpdateStateFile))
113 {
114 phosphor::logging::log<phosphor::logging::level::INFO>(
115 "usb-code-update-state file does not exist");
116
117 unitMaskedState = false;
118 unitEnabledState = true;
119 unitRunningState = true;
120 setUSBCodeUpdateState(unitEnabledState);
121 return;
122 }
123
124 std::ifstream file(usbCodeUpdateStateFile);
125 cereal::JSONInputArchive archive(file);
126 UsbCodeUpdateStateMap usbCodeUpdateState;
127 archive(usbCodeUpdateState);
128
129 auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
130 if (iterMask != usbCodeUpdateState.end())
131 {
132 unitMaskedState = iterMask->second;
133 if (unitMaskedState)
134 {
135 unitEnabledState = !unitMaskedState;
136 unitRunningState = !unitMaskedState;
137 setUSBCodeUpdateState(unitEnabledState);
138 return;
139 }
140
141 auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
142 if (iterEnable != usbCodeUpdateState.end())
143 {
144 unitEnabledState = iterEnable->second;
145 unitRunningState = iterEnable->second;
146 setUSBCodeUpdateState(unitEnabledState);
147 }
148 }
149}
150#endif
151
Vernon Maueryba2c0832020-07-15 10:02:38 -0700152void ServiceConfig::updateSocketProperties(
153 const boost::container::flat_map<std::string, VariantType>& propertyMap)
154{
155 auto listenIt = propertyMap.find("Listen");
156 if (listenIt != propertyMap.end())
157 {
158 auto listenVal =
159 std::get<std::vector<std::tuple<std::string, std::string>>>(
160 listenIt->second);
161 if (listenVal.size())
162 {
163 protocol = std::get<0>(listenVal[0]);
164 std::string port = std::get<1>(listenVal[0]);
165 auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
166 nullptr, 10);
167 if (tmp > std::numeric_limits<uint16_t>::max())
168 {
169 throw std::out_of_range("Out of range");
170 }
171 portNum = tmp;
172 if (sockAttrIface && sockAttrIface->is_initialized())
173 {
174 internalSet = true;
175 sockAttrIface->set_property(sockAttrPropPort, portNum);
176 internalSet = false;
177 }
178 }
179 }
180}
181
182void ServiceConfig::updateServiceProperties(
183 const boost::container::flat_map<std::string, VariantType>& propertyMap)
184{
185 auto stateIt = propertyMap.find("UnitFileState");
186 if (stateIt != propertyMap.end())
187 {
188 stateValue = std::get<std::string>(stateIt->second);
189 unitEnabledState = unitMaskedState = false;
190 if (stateValue == stateMasked)
191 {
192 unitMaskedState = true;
193 }
194 else if (stateValue == stateEnabled)
195 {
196 unitEnabledState = true;
197 }
198 if (srvCfgIface && srvCfgIface->is_initialized())
199 {
200 internalSet = true;
201 srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
202 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
203 internalSet = false;
204 }
205 }
206 auto subStateIt = propertyMap.find("SubState");
207 if (subStateIt != propertyMap.end())
208 {
209 subStateValue = std::get<std::string>(subStateIt->second);
George Liua19b5092021-05-24 15:54:02 +0800210 if (subStateValue == subStateRunning ||
211 subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700212 {
213 unitRunningState = true;
214 }
215 if (srvCfgIface && srvCfgIface->is_initialized())
216 {
217 internalSet = true;
218 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
219 internalSet = false;
220 }
221 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800222
223#ifdef USB_CODE_UPDATE
224 if (objPath == usbCodeUpdateObjectPath)
225 {
226 getUSBCodeUpdateStateFromFile();
227 }
228#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700229}
230
231void ServiceConfig::queryAndUpdateProperties()
232{
George Liua19b5092021-05-24 15:54:02 +0800233 std::string objectPath =
234 isDropBearService ? socketObjectPath : serviceObjectPath;
235 if (objectPath.empty())
236 {
237 return;
238 }
239
Vernon Maueryba2c0832020-07-15 10:02:38 -0700240 conn->async_method_call(
241 [this](boost::system::error_code ec,
242 const boost::container::flat_map<std::string, VariantType>&
243 propertyMap) {
244 if (ec)
245 {
George Liucb267c82022-01-05 17:53:28 +0800246 lg2::error(
247 "async_method_call error: Failed to service unit properties: {EC}",
248 "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700249 return;
250 }
251 try
252 {
253 updateServiceProperties(propertyMap);
254 if (!socketObjectPath.empty())
255 {
256 conn->async_method_call(
257 [this](boost::system::error_code ec,
258 const boost::container::flat_map<
259 std::string, VariantType>& propertyMap) {
260 if (ec)
261 {
George Liucb267c82022-01-05 17:53:28 +0800262 lg2::error(
263 "async_method_call error: Failed to get all property: {EC}",
264 "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700265 return;
266 }
267 try
268 {
269 updateSocketProperties(propertyMap);
270 if (!srvCfgIface)
271 {
272 registerProperties();
273 }
274 }
275 catch (const std::exception& e)
276 {
George Liucb267c82022-01-05 17:53:28 +0800277 lg2::error(
278 "Exception in getting socket properties: {ERROR}",
279 "ERROR", e);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700280 return;
281 }
282 },
283 sysdService, socketObjectPath, dBusPropIntf,
284 dBusGetAllMethod, sysdSocketIntf);
285 }
286 else if (!srvCfgIface)
287 {
288 registerProperties();
289 }
290 }
291 catch (const std::exception& e)
292 {
George Liucb267c82022-01-05 17:53:28 +0800293 lg2::error("Exception in getting socket properties: {ERROR}",
294 "ERROR", e);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700295 return;
296 }
297 },
George Liua19b5092021-05-24 15:54:02 +0800298 sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700299 return;
300}
301
302void ServiceConfig::createSocketOverrideConf()
303{
304 if (!socketObjectPath.empty())
305 {
306 std::string socketUnitName(instantiatedUnitName + ".socket");
307 /// Check override socket directory exist, if not create it.
308 std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
309 ovrUnitFileDir += socketUnitName;
310 ovrUnitFileDir += ".d";
311 if (!std::filesystem::exists(ovrUnitFileDir))
312 {
313 if (!std::filesystem::create_directories(ovrUnitFileDir))
314 {
George Liucb267c82022-01-05 17:53:28 +0800315 lg2::error("Unable to create the {DIR} directory.", "DIR",
316 ovrUnitFileDir);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700317 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
318 Common::Error::InternalFailure>();
319 }
320 }
321 overrideConfDir = std::string(ovrUnitFileDir);
322 }
323}
324
325ServiceConfig::ServiceConfig(
326 sdbusplus::asio::object_server& srv_,
327 std::shared_ptr<sdbusplus::asio::connection>& conn_,
328 const std::string& objPath_, const std::string& baseUnitName_,
329 const std::string& instanceName_, const std::string& serviceObjPath_,
330 const std::string& socketObjPath_) :
331 conn(conn_),
332 server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
333 instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
334 socketObjectPath(socketObjPath_)
335{
George Liua19b5092021-05-24 15:54:02 +0800336 if (baseUnitName == "dropbear")
337 {
338 isDropBearService = true;
339 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700340 instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
341 updatedFlag = 0;
342 queryAndUpdateProperties();
343 return;
344}
345
346std::string ServiceConfig::getSocketUnitName()
347{
348 return instantiatedUnitName + ".socket";
349}
350
351std::string ServiceConfig::getServiceUnitName()
352{
353 return instantiatedUnitName + ".service";
354}
355
356bool ServiceConfig::isMaskedOut()
357{
358 // return true if state is masked & no request to update the maskedState
359 return (
360 stateValue == "masked" &&
361 !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
362}
363
364void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
365{
366 if (!updatedFlag || isMaskedOut())
367 {
368 // No updates / masked - Just return.
369 return;
370 }
George Liucb267c82022-01-05 17:53:28 +0800371 lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
George Liua19b5092021-05-24 15:54:02 +0800372 if (subStateValue == subStateRunning || subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700373 {
374 if (!socketObjectPath.empty())
375 {
376 systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
377 }
George Liua19b5092021-05-24 15:54:02 +0800378 if (!isDropBearService)
379 {
380 systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
381 }
382 else
383 {
384 // Get the ListUnits property, find all the services of
385 // `dropbear@<ip><port>.service` and stop the service through
386 // the systemdUnitAction method
387 boost::system::error_code ec;
388 auto listUnits =
389 conn->yield_method_call<std::vector<ListUnitsType>>(
390 yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
391 "ListUnits");
392
393 checkAndThrowInternalFailure(
394 ec, "yield_method_call error: ListUnits failed");
395
396 for (const auto& unit : listUnits)
397 {
398 const auto& service =
399 std::get<static_cast<int>(ListUnitElements::name)>(unit);
400 const auto& status =
401 std::get<static_cast<int>(ListUnitElements::subState)>(
402 unit);
403 if (service.find("dropbear@") != std::string::npos &&
404 service.find(".service") != std::string::npos &&
405 status == subStateRunning)
406 {
407 systemdUnitAction(conn, yield, service, sysdStopUnit);
408 }
409 }
410 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700411 }
412
413 if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
414 {
415 createSocketOverrideConf();
416 // Create override config file and write data.
417 std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
418 std::string tmpFile{ovrCfgFile + "_tmp"};
419 std::ofstream cfgFile(tmpFile, std::ios::out);
420 if (!cfgFile.good())
421 {
George Liucb267c82022-01-05 17:53:28 +0800422 lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
423 tmpFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700424 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
425 Error::InternalFailure>();
426 }
427
428 // Write the socket header
429 cfgFile << "[Socket]\n";
430 // Listen
431 cfgFile << "Listen" << protocol << "="
432 << "\n";
433 cfgFile << "Listen" << protocol << "=" << portNum << "\n";
434 cfgFile.close();
435
436 if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
437 {
George Liucb267c82022-01-05 17:53:28 +0800438 lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
439 "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700440 std::remove(tmpFile.c_str());
441 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
442 Error::InternalFailure>();
443 }
444 }
445
446 if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
447 (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
448 {
449 std::vector<std::string> unitFiles;
450 if (socketObjectPath.empty())
451 {
452 unitFiles = {getServiceUnitName()};
453 }
George Liua19b5092021-05-24 15:54:02 +0800454 else if (!socketObjectPath.empty() && isDropBearService)
455 {
456 unitFiles = {getSocketUnitName()};
457 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700458 else
459 {
460 unitFiles = {getSocketUnitName(), getServiceUnitName()};
461 }
462 systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
463 unitMaskedState, unitEnabledState);
464 }
465 return;
466}
467void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
468{
469 if (!updatedFlag || isMaskedOut())
470 {
471 // No updates. Just return.
472 return;
473 }
474
475 if (unitRunningState)
476 {
477 if (!socketObjectPath.empty())
478 {
479 systemdUnitAction(conn, yield, getSocketUnitName(),
480 sysdRestartUnit);
481 }
George Liua19b5092021-05-24 15:54:02 +0800482 if (!isDropBearService)
483 {
484 systemdUnitAction(conn, yield, getServiceUnitName(),
485 sysdRestartUnit);
486 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700487 }
488
489 // Reset the flag
490 updatedFlag = 0;
491
George Liucb267c82022-01-05 17:53:28 +0800492 lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700493
494 queryAndUpdateProperties();
495 return;
496}
497
498void ServiceConfig::startServiceRestartTimer()
499{
500 timer->expires_after(std::chrono::seconds(restartTimeout));
501 timer->async_wait([this](const boost::system::error_code& ec) {
502 if (ec == boost::asio::error::operation_aborted)
503 {
504 // Timer reset.
505 return;
506 }
507 else if (ec)
508 {
George Liucb267c82022-01-05 17:53:28 +0800509 lg2::error("async wait error: {EC}", "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700510 return;
511 }
512 updateInProgress = true;
513 boost::asio::spawn(conn->get_io_context(),
514 [this](boost::asio::yield_context yield) {
515 // Stop and apply configuration for all objects
516 for (auto& srvMgrObj : srvMgrObjects)
517 {
518 auto& srvObj = srvMgrObj.second;
519 if (srvObj->updatedFlag)
520 {
521 srvObj->stopAndApplyUnitConfig(yield);
522 }
523 }
524 // Do system reload
525 systemdDaemonReload(conn, yield);
526 // restart unit config.
527 for (auto& srvMgrObj : srvMgrObjects)
528 {
529 auto& srvObj = srvMgrObj.second;
530 if (srvObj->updatedFlag)
531 {
532 srvObj->restartUnitConfig(yield);
533 }
534 }
535 updateInProgress = false;
536 });
537 });
538}
539
540void ServiceConfig::registerProperties()
541{
542 srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
543
544 if (!socketObjectPath.empty())
545 {
546 sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
547 sockAttrIface->register_property(
548 sockAttrPropPort, portNum,
549 [this](const uint16_t& req, uint16_t& res) {
550 if (!internalSet)
551 {
552 if (req == res)
553 {
554 return 1;
555 }
556 if (updateInProgress)
557 {
558 return 0;
559 }
560 portNum = req;
561 updatedFlag |=
562 (1 << static_cast<uint8_t>(UpdatedProp::port));
563 startServiceRestartTimer();
564 }
565 res = req;
566 return 1;
567 });
568 }
569
570 srvCfgIface->register_property(
571 srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
572 if (!internalSet)
573 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800574#ifdef USB_CODE_UPDATE
575 if (objPath == usbCodeUpdateObjectPath)
576 {
577 unitMaskedState = req;
578 unitEnabledState = !unitMaskedState;
579 unitRunningState = !unitMaskedState;
580 internalSet = true;
581 srvCfgIface->set_property(srvCfgPropEnabled,
582 unitEnabledState);
583 srvCfgIface->set_property(srvCfgPropRunning,
584 unitRunningState);
585 srvCfgIface->set_property(srvCfgPropMasked,
586 unitMaskedState);
587 internalSet = false;
588 setUSBCodeUpdateState(unitEnabledState);
589 saveUSBCodeUpdateStateToFile(unitMaskedState,
590 unitEnabledState);
591 return 1;
592 }
593#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700594 if (req == res)
595 {
596 return 1;
597 }
598 if (updateInProgress)
599 {
600 return 0;
601 }
602 unitMaskedState = req;
603 unitEnabledState = !unitMaskedState;
604 unitRunningState = !unitMaskedState;
605 updatedFlag |=
606 (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
607 (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
608 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
609 internalSet = true;
610 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
611 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
612 internalSet = false;
613 startServiceRestartTimer();
614 }
615 res = req;
616 return 1;
617 });
618
619 srvCfgIface->register_property(
620 srvCfgPropEnabled, unitEnabledState,
621 [this](const bool& req, bool& res) {
622 if (!internalSet)
623 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800624#ifdef USB_CODE_UPDATE
625 if (objPath == usbCodeUpdateObjectPath)
626 {
627 if (unitMaskedState)
628 { // block updating if masked
629 phosphor::logging::log<phosphor::logging::level::ERR>(
630 "Invalid value specified");
631 return -EINVAL;
632 }
633 unitEnabledState = req;
634 unitRunningState = req;
635 internalSet = true;
636 srvCfgIface->set_property(srvCfgPropEnabled,
637 unitEnabledState);
638 srvCfgIface->set_property(srvCfgPropRunning,
639 unitRunningState);
640 internalSet = false;
641 setUSBCodeUpdateState(unitEnabledState);
642 saveUSBCodeUpdateStateToFile(unitMaskedState,
643 unitEnabledState);
644 res = req;
645 return 1;
646 }
647#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700648 if (req == res)
649 {
650 return 1;
651 }
652 if (updateInProgress)
653 {
654 return 0;
655 }
656 if (unitMaskedState)
657 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800658 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700659 return -EINVAL;
660 }
661 unitEnabledState = req;
662 updatedFlag |=
663 (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
664 startServiceRestartTimer();
665 }
666 res = req;
667 return 1;
668 });
669
670 srvCfgIface->register_property(
671 srvCfgPropRunning, unitRunningState,
672 [this](const bool& req, bool& res) {
673 if (!internalSet)
674 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800675#ifdef USB_CODE_UPDATE
676 if (objPath == usbCodeUpdateObjectPath)
677 {
678 if (unitMaskedState)
679 { // block updating if masked
680 phosphor::logging::log<phosphor::logging::level::ERR>(
681 "Invalid value specified");
682 return -EINVAL;
683 }
684 unitEnabledState = req;
685 unitRunningState = req;
686 internalSet = true;
687 srvCfgIface->set_property(srvCfgPropEnabled,
688 unitEnabledState);
689 srvCfgIface->set_property(srvCfgPropRunning,
690 unitRunningState);
691 internalSet = false;
692 setUSBCodeUpdateState(unitEnabledState);
693 saveUSBCodeUpdateStateToFile(unitMaskedState,
694 unitEnabledState);
695 res = req;
696 return 1;
697 }
698#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700699 if (req == res)
700 {
701 return 1;
702 }
703 if (updateInProgress)
704 {
705 return 0;
706 }
707 if (unitMaskedState)
708 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800709 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700710 return -EINVAL;
711 }
712 unitRunningState = req;
713 updatedFlag |=
714 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
715 startServiceRestartTimer();
716 }
717 res = req;
718 return 1;
719 });
720
721 srvCfgIface->initialize();
722 if (!socketObjectPath.empty())
723 {
724 sockAttrIface->initialize();
725 }
726 return;
727}
728
729} // namespace service
730} // namespace phosphor