blob: 36857b8a9884c7bea0a153ad6b2ab86acaf7b4d5 [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 =
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800234 isSocketActivatedService ? socketObjectPath : serviceObjectPath;
George Liua19b5092021-05-24 15:54:02 +0800235 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{
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800336 isSocketActivatedService = serviceObjectPath.empty();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700337 instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
338 updatedFlag = 0;
339 queryAndUpdateProperties();
340 return;
341}
342
343std::string ServiceConfig::getSocketUnitName()
344{
345 return instantiatedUnitName + ".socket";
346}
347
348std::string ServiceConfig::getServiceUnitName()
349{
350 return instantiatedUnitName + ".service";
351}
352
353bool ServiceConfig::isMaskedOut()
354{
355 // return true if state is masked & no request to update the maskedState
356 return (
357 stateValue == "masked" &&
358 !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
359}
360
361void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
362{
363 if (!updatedFlag || isMaskedOut())
364 {
365 // No updates / masked - Just return.
366 return;
367 }
George Liucb267c82022-01-05 17:53:28 +0800368 lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
George Liua19b5092021-05-24 15:54:02 +0800369 if (subStateValue == subStateRunning || subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700370 {
371 if (!socketObjectPath.empty())
372 {
373 systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
374 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800375 if (!isSocketActivatedService)
George Liua19b5092021-05-24 15:54:02 +0800376 {
377 systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
378 }
379 else
380 {
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800381 // For socket-activated service, each connection will spawn a
382 // service instance from template. Need to find all spawned service
383 // `<unitName>@<attribute>.service` and stop them through the
384 // systemdUnitAction method
George Liua19b5092021-05-24 15:54:02 +0800385 boost::system::error_code ec;
386 auto listUnits =
387 conn->yield_method_call<std::vector<ListUnitsType>>(
388 yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
389 "ListUnits");
390
391 checkAndThrowInternalFailure(
392 ec, "yield_method_call error: ListUnits failed");
393
394 for (const auto& unit : listUnits)
395 {
396 const auto& service =
397 std::get<static_cast<int>(ListUnitElements::name)>(unit);
398 const auto& status =
399 std::get<static_cast<int>(ListUnitElements::subState)>(
400 unit);
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800401 if (service.find(baseUnitName + "@") != std::string::npos &&
George Liua19b5092021-05-24 15:54:02 +0800402 service.find(".service") != std::string::npos &&
403 status == subStateRunning)
404 {
405 systemdUnitAction(conn, yield, service, sysdStopUnit);
406 }
407 }
408 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700409 }
410
411 if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
412 {
413 createSocketOverrideConf();
414 // Create override config file and write data.
415 std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
416 std::string tmpFile{ovrCfgFile + "_tmp"};
417 std::ofstream cfgFile(tmpFile, std::ios::out);
418 if (!cfgFile.good())
419 {
George Liucb267c82022-01-05 17:53:28 +0800420 lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
421 tmpFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700422 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
423 Error::InternalFailure>();
424 }
425
426 // Write the socket header
427 cfgFile << "[Socket]\n";
428 // Listen
429 cfgFile << "Listen" << protocol << "="
430 << "\n";
431 cfgFile << "Listen" << protocol << "=" << portNum << "\n";
432 cfgFile.close();
433
434 if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
435 {
George Liucb267c82022-01-05 17:53:28 +0800436 lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
437 "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700438 std::remove(tmpFile.c_str());
439 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
440 Error::InternalFailure>();
441 }
442 }
443
444 if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
445 (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
446 {
447 std::vector<std::string> unitFiles;
448 if (socketObjectPath.empty())
449 {
450 unitFiles = {getServiceUnitName()};
451 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800452 else if (serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800453 {
454 unitFiles = {getSocketUnitName()};
455 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700456 else
457 {
458 unitFiles = {getSocketUnitName(), getServiceUnitName()};
459 }
460 systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
461 unitMaskedState, unitEnabledState);
462 }
463 return;
464}
465void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
466{
467 if (!updatedFlag || isMaskedOut())
468 {
469 // No updates. Just return.
470 return;
471 }
472
473 if (unitRunningState)
474 {
475 if (!socketObjectPath.empty())
476 {
477 systemdUnitAction(conn, yield, getSocketUnitName(),
478 sysdRestartUnit);
479 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800480 if (!serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800481 {
482 systemdUnitAction(conn, yield, getServiceUnitName(),
483 sysdRestartUnit);
484 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700485 }
486
487 // Reset the flag
488 updatedFlag = 0;
489
George Liucb267c82022-01-05 17:53:28 +0800490 lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700491
492 queryAndUpdateProperties();
493 return;
494}
495
496void ServiceConfig::startServiceRestartTimer()
497{
498 timer->expires_after(std::chrono::seconds(restartTimeout));
499 timer->async_wait([this](const boost::system::error_code& ec) {
500 if (ec == boost::asio::error::operation_aborted)
501 {
502 // Timer reset.
503 return;
504 }
505 else if (ec)
506 {
George Liucb267c82022-01-05 17:53:28 +0800507 lg2::error("async wait error: {EC}", "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700508 return;
509 }
510 updateInProgress = true;
511 boost::asio::spawn(conn->get_io_context(),
512 [this](boost::asio::yield_context yield) {
513 // Stop and apply configuration for all objects
514 for (auto& srvMgrObj : srvMgrObjects)
515 {
516 auto& srvObj = srvMgrObj.second;
517 if (srvObj->updatedFlag)
518 {
519 srvObj->stopAndApplyUnitConfig(yield);
520 }
521 }
522 // Do system reload
523 systemdDaemonReload(conn, yield);
524 // restart unit config.
525 for (auto& srvMgrObj : srvMgrObjects)
526 {
527 auto& srvObj = srvMgrObj.second;
528 if (srvObj->updatedFlag)
529 {
530 srvObj->restartUnitConfig(yield);
531 }
532 }
533 updateInProgress = false;
534 });
535 });
536}
537
538void ServiceConfig::registerProperties()
539{
540 srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
541
542 if (!socketObjectPath.empty())
543 {
544 sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
545 sockAttrIface->register_property(
546 sockAttrPropPort, portNum,
547 [this](const uint16_t& req, uint16_t& res) {
548 if (!internalSet)
549 {
550 if (req == res)
551 {
552 return 1;
553 }
554 if (updateInProgress)
555 {
556 return 0;
557 }
558 portNum = req;
559 updatedFlag |=
560 (1 << static_cast<uint8_t>(UpdatedProp::port));
561 startServiceRestartTimer();
562 }
563 res = req;
564 return 1;
565 });
566 }
567
568 srvCfgIface->register_property(
569 srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
570 if (!internalSet)
571 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800572#ifdef USB_CODE_UPDATE
573 if (objPath == usbCodeUpdateObjectPath)
574 {
575 unitMaskedState = req;
576 unitEnabledState = !unitMaskedState;
577 unitRunningState = !unitMaskedState;
578 internalSet = true;
579 srvCfgIface->set_property(srvCfgPropEnabled,
580 unitEnabledState);
581 srvCfgIface->set_property(srvCfgPropRunning,
582 unitRunningState);
583 srvCfgIface->set_property(srvCfgPropMasked,
584 unitMaskedState);
585 internalSet = false;
586 setUSBCodeUpdateState(unitEnabledState);
587 saveUSBCodeUpdateStateToFile(unitMaskedState,
588 unitEnabledState);
589 return 1;
590 }
591#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700592 if (req == res)
593 {
594 return 1;
595 }
596 if (updateInProgress)
597 {
598 return 0;
599 }
600 unitMaskedState = req;
601 unitEnabledState = !unitMaskedState;
602 unitRunningState = !unitMaskedState;
603 updatedFlag |=
604 (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
605 (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
606 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
607 internalSet = true;
608 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
609 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
610 internalSet = false;
611 startServiceRestartTimer();
612 }
613 res = req;
614 return 1;
615 });
616
617 srvCfgIface->register_property(
618 srvCfgPropEnabled, unitEnabledState,
619 [this](const bool& req, bool& res) {
620 if (!internalSet)
621 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800622#ifdef USB_CODE_UPDATE
623 if (objPath == usbCodeUpdateObjectPath)
624 {
625 if (unitMaskedState)
626 { // block updating if masked
627 phosphor::logging::log<phosphor::logging::level::ERR>(
628 "Invalid value specified");
629 return -EINVAL;
630 }
631 unitEnabledState = req;
632 unitRunningState = req;
633 internalSet = true;
634 srvCfgIface->set_property(srvCfgPropEnabled,
635 unitEnabledState);
636 srvCfgIface->set_property(srvCfgPropRunning,
637 unitRunningState);
638 internalSet = false;
639 setUSBCodeUpdateState(unitEnabledState);
640 saveUSBCodeUpdateStateToFile(unitMaskedState,
641 unitEnabledState);
642 res = req;
643 return 1;
644 }
645#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700646 if (req == res)
647 {
648 return 1;
649 }
650 if (updateInProgress)
651 {
652 return 0;
653 }
654 if (unitMaskedState)
655 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800656 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700657 return -EINVAL;
658 }
659 unitEnabledState = req;
660 updatedFlag |=
661 (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
662 startServiceRestartTimer();
663 }
664 res = req;
665 return 1;
666 });
667
668 srvCfgIface->register_property(
669 srvCfgPropRunning, unitRunningState,
670 [this](const bool& req, bool& res) {
671 if (!internalSet)
672 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800673#ifdef USB_CODE_UPDATE
674 if (objPath == usbCodeUpdateObjectPath)
675 {
676 if (unitMaskedState)
677 { // block updating if masked
678 phosphor::logging::log<phosphor::logging::level::ERR>(
679 "Invalid value specified");
680 return -EINVAL;
681 }
682 unitEnabledState = req;
683 unitRunningState = req;
684 internalSet = true;
685 srvCfgIface->set_property(srvCfgPropEnabled,
686 unitEnabledState);
687 srvCfgIface->set_property(srvCfgPropRunning,
688 unitRunningState);
689 internalSet = false;
690 setUSBCodeUpdateState(unitEnabledState);
691 saveUSBCodeUpdateStateToFile(unitMaskedState,
692 unitEnabledState);
693 res = req;
694 return 1;
695 }
696#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700697 if (req == res)
698 {
699 return 1;
700 }
701 if (updateInProgress)
702 {
703 return 0;
704 }
705 if (unitMaskedState)
706 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800707 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700708 return -EINVAL;
709 }
710 unitRunningState = req;
711 updatedFlag |=
712 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
713 startServiceRestartTimer();
714 }
715 res = req;
716 return 1;
717 });
718
719 srvCfgIface->initialize();
720 if (!socketObjectPath.empty())
721 {
722 sockAttrIface->initialize();
723 }
724 return;
725}
726
727} // namespace service
728} // namespace phosphor