blob: 3a771d94bd57304bacf36fd781f771c709e7ea05 [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";
Chicago Duan25a0f632021-11-11 16:32:07 +080056
57using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;
58
59void ServiceConfig::setUSBCodeUpdateState(const bool& state)
60{
61 // Enable usb code update
62 if (state)
63 {
64 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
65 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080066 lg2::info("Enable usb code update");
Chicago Duan25a0f632021-11-11 16:32:07 +080067 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
68 }
69 return;
70 }
71
72 // Disable usb code update
73 if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
74 {
75 std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
76 }
77 std::error_code ec;
78 std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
79 ec);
80 if (ec)
81 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080082 lg2::error("Disable usb code update failed");
Chicago Duan25a0f632021-11-11 16:32:07 +080083 return;
84 }
Jiaqing Zhaof27f4312022-04-02 17:42:46 +080085 lg2::info("Disable usb code update");
Chicago Duan25a0f632021-11-11 16:32:07 +080086}
87
88void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
89 const bool& enabledState)
90{
91 if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
92 {
93 std::filesystem::create_directories(usbCodeUpdateStateFilePath);
94 }
95
96 UsbCodeUpdateStateMap usbCodeUpdateState;
97 usbCodeUpdateState[srvCfgPropMasked] = maskedState;
98 usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
99
100 std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
101 cereal::JSONOutputArchive archive(file);
102 archive(CEREAL_NVP(usbCodeUpdateState));
103}
104
105void ServiceConfig::getUSBCodeUpdateStateFromFile()
106{
107 if (!std::filesystem::exists(usbCodeUpdateStateFile))
108 {
Jiaqing Zhaof27f4312022-04-02 17:42:46 +0800109 lg2::info("usb-code-update-state file does not exist");
Chicago Duan25a0f632021-11-11 16:32:07 +0800110
111 unitMaskedState = false;
112 unitEnabledState = true;
113 unitRunningState = true;
114 setUSBCodeUpdateState(unitEnabledState);
115 return;
116 }
117
118 std::ifstream file(usbCodeUpdateStateFile);
119 cereal::JSONInputArchive archive(file);
120 UsbCodeUpdateStateMap usbCodeUpdateState;
121 archive(usbCodeUpdateState);
122
123 auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
124 if (iterMask != usbCodeUpdateState.end())
125 {
126 unitMaskedState = iterMask->second;
127 if (unitMaskedState)
128 {
129 unitEnabledState = !unitMaskedState;
130 unitRunningState = !unitMaskedState;
131 setUSBCodeUpdateState(unitEnabledState);
132 return;
133 }
134
135 auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
136 if (iterEnable != usbCodeUpdateState.end())
137 {
138 unitEnabledState = iterEnable->second;
139 unitRunningState = iterEnable->second;
140 setUSBCodeUpdateState(unitEnabledState);
141 }
142 }
143}
144#endif
145
Vernon Maueryba2c0832020-07-15 10:02:38 -0700146void ServiceConfig::updateSocketProperties(
147 const boost::container::flat_map<std::string, VariantType>& propertyMap)
148{
149 auto listenIt = propertyMap.find("Listen");
150 if (listenIt != propertyMap.end())
151 {
152 auto listenVal =
153 std::get<std::vector<std::tuple<std::string, std::string>>>(
154 listenIt->second);
155 if (listenVal.size())
156 {
157 protocol = std::get<0>(listenVal[0]);
158 std::string port = std::get<1>(listenVal[0]);
159 auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
160 nullptr, 10);
161 if (tmp > std::numeric_limits<uint16_t>::max())
162 {
163 throw std::out_of_range("Out of range");
164 }
165 portNum = tmp;
166 if (sockAttrIface && sockAttrIface->is_initialized())
167 {
168 internalSet = true;
169 sockAttrIface->set_property(sockAttrPropPort, portNum);
170 internalSet = false;
171 }
172 }
173 }
174}
175
176void ServiceConfig::updateServiceProperties(
177 const boost::container::flat_map<std::string, VariantType>& propertyMap)
178{
179 auto stateIt = propertyMap.find("UnitFileState");
180 if (stateIt != propertyMap.end())
181 {
182 stateValue = std::get<std::string>(stateIt->second);
183 unitEnabledState = unitMaskedState = false;
184 if (stateValue == stateMasked)
185 {
186 unitMaskedState = true;
187 }
188 else if (stateValue == stateEnabled)
189 {
190 unitEnabledState = true;
191 }
192 if (srvCfgIface && srvCfgIface->is_initialized())
193 {
194 internalSet = true;
195 srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
196 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
197 internalSet = false;
198 }
199 }
200 auto subStateIt = propertyMap.find("SubState");
201 if (subStateIt != propertyMap.end())
202 {
203 subStateValue = std::get<std::string>(subStateIt->second);
George Liua19b5092021-05-24 15:54:02 +0800204 if (subStateValue == subStateRunning ||
205 subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700206 {
207 unitRunningState = true;
208 }
209 if (srvCfgIface && srvCfgIface->is_initialized())
210 {
211 internalSet = true;
212 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
213 internalSet = false;
214 }
215 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800216
217#ifdef USB_CODE_UPDATE
Jiaqing Zhao430d7ea2022-04-01 23:23:25 +0800218 if (baseUnitName == usbCodeUpdateUnitName)
Chicago Duan25a0f632021-11-11 16:32:07 +0800219 {
220 getUSBCodeUpdateStateFromFile();
221 }
222#endif
Vernon Maueryba2c0832020-07-15 10:02:38 -0700223}
224
225void ServiceConfig::queryAndUpdateProperties()
226{
Patrick Williamsdfc72702023-05-10 07:51:18 -0500227 std::string objectPath = isSocketActivatedService ? socketObjectPath
228 : serviceObjectPath;
George Liua19b5092021-05-24 15:54:02 +0800229 if (objectPath.empty())
230 {
231 return;
232 }
233
Vernon Maueryba2c0832020-07-15 10:02:38 -0700234 conn->async_method_call(
235 [this](boost::system::error_code ec,
236 const boost::container::flat_map<std::string, VariantType>&
237 propertyMap) {
Patrick Williamsdfc72702023-05-10 07:51:18 -0500238 if (ec)
239 {
240 lg2::error(
241 "async_method_call error: Failed to service unit properties: {EC}",
242 "EC", ec.value());
243 return;
244 }
245 try
246 {
247 updateServiceProperties(propertyMap);
248 if (!socketObjectPath.empty())
Vernon Maueryba2c0832020-07-15 10:02:38 -0700249 {
Patrick Williamsdfc72702023-05-10 07:51:18 -0500250 conn->async_method_call(
251 [this](boost::system::error_code ec,
252 const boost::container::flat_map<
253 std::string, VariantType>& propertyMap) {
254 if (ec)
255 {
256 lg2::error(
257 "async_method_call error: Failed to get all property: {EC}",
258 "EC", ec.value());
259 return;
260 }
261 try
262 {
263 updateSocketProperties(propertyMap);
264 if (!srvCfgIface)
265 {
266 registerProperties();
267 }
268 }
269 catch (const std::exception& e)
270 {
271 lg2::error(
272 "Exception in getting socket properties: {ERROR}",
273 "ERROR", e);
274 return;
275 }
Patrick Williamsd8effd62023-10-20 11:19:46 -0500276 },
Patrick Williamsdfc72702023-05-10 07:51:18 -0500277 sysdService, socketObjectPath, dBusPropIntf,
278 dBusGetAllMethod, sysdSocketIntf);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700279 }
Patrick Williamsdfc72702023-05-10 07:51:18 -0500280 else if (!srvCfgIface)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700281 {
Patrick Williamsdfc72702023-05-10 07:51:18 -0500282 registerProperties();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700283 }
Patrick Williamsdfc72702023-05-10 07:51:18 -0500284 }
285 catch (const std::exception& e)
286 {
287 lg2::error("Exception in getting socket properties: {ERROR}",
288 "ERROR", e);
289 return;
290 }
Patrick Williamsd8effd62023-10-20 11:19:46 -0500291 },
George Liua19b5092021-05-24 15:54:02 +0800292 sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700293 return;
294}
295
296void ServiceConfig::createSocketOverrideConf()
297{
298 if (!socketObjectPath.empty())
299 {
300 std::string socketUnitName(instantiatedUnitName + ".socket");
301 /// Check override socket directory exist, if not create it.
302 std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
303 ovrUnitFileDir += socketUnitName;
304 ovrUnitFileDir += ".d";
305 if (!std::filesystem::exists(ovrUnitFileDir))
306 {
307 if (!std::filesystem::create_directories(ovrUnitFileDir))
308 {
George Liucb267c82022-01-05 17:53:28 +0800309 lg2::error("Unable to create the {DIR} directory.", "DIR",
310 ovrUnitFileDir);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700311 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
312 Common::Error::InternalFailure>();
313 }
314 }
315 overrideConfDir = std::string(ovrUnitFileDir);
316 }
317}
318
319ServiceConfig::ServiceConfig(
320 sdbusplus::asio::object_server& srv_,
321 std::shared_ptr<sdbusplus::asio::connection>& conn_,
322 const std::string& objPath_, const std::string& baseUnitName_,
323 const std::string& instanceName_, const std::string& serviceObjPath_,
324 const std::string& socketObjPath_) :
325 conn(conn_),
326 server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
327 instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
328 socketObjectPath(socketObjPath_)
329{
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800330 isSocketActivatedService = serviceObjectPath.empty();
Vernon Maueryba2c0832020-07-15 10:02:38 -0700331 instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
332 updatedFlag = 0;
333 queryAndUpdateProperties();
334 return;
335}
336
337std::string ServiceConfig::getSocketUnitName()
338{
339 return instantiatedUnitName + ".socket";
340}
341
342std::string ServiceConfig::getServiceUnitName()
343{
344 return instantiatedUnitName + ".service";
345}
346
347bool ServiceConfig::isMaskedOut()
348{
349 // return true if state is masked & no request to update the maskedState
350 return (
351 stateValue == "masked" &&
352 !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
353}
354
355void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
356{
357 if (!updatedFlag || isMaskedOut())
358 {
359 // No updates / masked - Just return.
360 return;
361 }
George Liucb267c82022-01-05 17:53:28 +0800362 lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
George Liua19b5092021-05-24 15:54:02 +0800363 if (subStateValue == subStateRunning || subStateValue == subStateListening)
Vernon Maueryba2c0832020-07-15 10:02:38 -0700364 {
365 if (!socketObjectPath.empty())
366 {
367 systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
368 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800369 if (!isSocketActivatedService)
George Liua19b5092021-05-24 15:54:02 +0800370 {
371 systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
372 }
373 else
374 {
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800375 // For socket-activated service, each connection will spawn a
376 // service instance from template. Need to find all spawned service
377 // `<unitName>@<attribute>.service` and stop them through the
378 // systemdUnitAction method
George Liua19b5092021-05-24 15:54:02 +0800379 boost::system::error_code ec;
380 auto listUnits =
381 conn->yield_method_call<std::vector<ListUnitsType>>(
382 yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
383 "ListUnits");
384
385 checkAndThrowInternalFailure(
386 ec, "yield_method_call error: ListUnits failed");
387
388 for (const auto& unit : listUnits)
389 {
390 const auto& service =
391 std::get<static_cast<int>(ListUnitElements::name)>(unit);
392 const auto& status =
393 std::get<static_cast<int>(ListUnitElements::subState)>(
394 unit);
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800395 if (service.find(baseUnitName + "@") != std::string::npos &&
George Liua19b5092021-05-24 15:54:02 +0800396 service.find(".service") != std::string::npos &&
397 status == subStateRunning)
398 {
399 systemdUnitAction(conn, yield, service, sysdStopUnit);
400 }
401 }
402 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700403 }
404
405 if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
406 {
407 createSocketOverrideConf();
408 // Create override config file and write data.
409 std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
410 std::string tmpFile{ovrCfgFile + "_tmp"};
411 std::ofstream cfgFile(tmpFile, std::ios::out);
412 if (!cfgFile.good())
413 {
George Liucb267c82022-01-05 17:53:28 +0800414 lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
415 tmpFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700416 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
417 Error::InternalFailure>();
418 }
419
420 // Write the socket header
421 cfgFile << "[Socket]\n";
422 // Listen
423 cfgFile << "Listen" << protocol << "="
424 << "\n";
425 cfgFile << "Listen" << protocol << "=" << portNum << "\n";
426 cfgFile.close();
427
428 if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
429 {
George Liucb267c82022-01-05 17:53:28 +0800430 lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
431 "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700432 std::remove(tmpFile.c_str());
433 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
434 Error::InternalFailure>();
435 }
436 }
437
438 if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
439 (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
440 {
441 std::vector<std::string> unitFiles;
442 if (socketObjectPath.empty())
443 {
444 unitFiles = {getServiceUnitName()};
445 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800446 else if (serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800447 {
448 unitFiles = {getSocketUnitName()};
449 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700450 else
451 {
452 unitFiles = {getSocketUnitName(), getServiceUnitName()};
453 }
454 systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
455 unitMaskedState, unitEnabledState);
456 }
457 return;
458}
459void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
460{
461 if (!updatedFlag || isMaskedOut())
462 {
463 // No updates. Just return.
464 return;
465 }
466
467 if (unitRunningState)
468 {
469 if (!socketObjectPath.empty())
470 {
471 systemdUnitAction(conn, yield, getSocketUnitName(),
472 sysdRestartUnit);
473 }
Jiaqing Zhaof4766832022-02-28 14:28:18 +0800474 if (!serviceObjectPath.empty())
George Liua19b5092021-05-24 15:54:02 +0800475 {
476 systemdUnitAction(conn, yield, getServiceUnitName(),
477 sysdRestartUnit);
478 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700479 }
480
481 // Reset the flag
482 updatedFlag = 0;
483
George Liucb267c82022-01-05 17:53:28 +0800484 lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
Vernon Maueryba2c0832020-07-15 10:02:38 -0700485
486 queryAndUpdateProperties();
487 return;
488}
489
490void ServiceConfig::startServiceRestartTimer()
491{
492 timer->expires_after(std::chrono::seconds(restartTimeout));
493 timer->async_wait([this](const boost::system::error_code& ec) {
494 if (ec == boost::asio::error::operation_aborted)
495 {
496 // Timer reset.
497 return;
498 }
499 else if (ec)
500 {
George Liucb267c82022-01-05 17:53:28 +0800501 lg2::error("async wait error: {EC}", "EC", ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -0700502 return;
503 }
504 updateInProgress = true;
505 boost::asio::spawn(conn->get_io_context(),
506 [this](boost::asio::yield_context yield) {
Patrick Williamsdfc72702023-05-10 07:51:18 -0500507 // Stop and apply configuration for all objects
508 for (auto& srvMgrObj : srvMgrObjects)
509 {
510 auto& srvObj = srvMgrObj.second;
511 if (srvObj->updatedFlag)
512 {
513 srvObj->stopAndApplyUnitConfig(yield);
514 }
515 }
516 // Do system reload
517 systemdDaemonReload(conn, yield);
518 // restart unit config.
519 for (auto& srvMgrObj : srvMgrObjects)
520 {
521 auto& srvObj = srvMgrObj.second;
522 if (srvObj->updatedFlag)
523 {
524 srvObj->restartUnitConfig(yield);
525 }
526 }
527 updateInProgress = false;
528 });
Vernon Maueryba2c0832020-07-15 10:02:38 -0700529 });
530}
531
532void ServiceConfig::registerProperties()
533{
534 srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
535
536 if (!socketObjectPath.empty())
537 {
538 sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
539 sockAttrIface->register_property(
540 sockAttrPropPort, portNum,
541 [this](const uint16_t& req, uint16_t& res) {
Vernon Maueryba2c0832020-07-15 10:02:38 -0700542 if (!internalSet)
543 {
544 if (req == res)
545 {
546 return 1;
547 }
548 if (updateInProgress)
549 {
550 return 0;
551 }
Patrick Williamsdfc72702023-05-10 07:51:18 -0500552 portNum = req;
553 updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::port));
Vernon Maueryba2c0832020-07-15 10:02:38 -0700554 startServiceRestartTimer();
555 }
556 res = req;
557 return 1;
Patrick Williamsd8effd62023-10-20 11:19:46 -0500558 });
Patrick Williamsdfc72702023-05-10 07:51:18 -0500559 }
Vernon Maueryba2c0832020-07-15 10:02:38 -0700560
Patrick Williamsdfc72702023-05-10 07:51:18 -0500561 srvCfgIface->register_property(srvCfgPropMasked, unitMaskedState,
562 [this](const bool& req, bool& res) {
563 if (!internalSet)
564 {
Chicago Duan25a0f632021-11-11 16:32:07 +0800565#ifdef USB_CODE_UPDATE
Patrick Williamsdfc72702023-05-10 07:51:18 -0500566 if (baseUnitName == usbCodeUpdateUnitName)
567 {
568 unitMaskedState = req;
569 unitEnabledState = !unitMaskedState;
570 unitRunningState = !unitMaskedState;
571 internalSet = true;
572 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
573 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
574 srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
575 internalSet = false;
576 setUSBCodeUpdateState(unitEnabledState);
577 saveUSBCodeUpdateStateToFile(unitMaskedState, unitEnabledState);
578 return 1;
579 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800580#endif
Patrick Williamsdfc72702023-05-10 07:51:18 -0500581 if (req == res)
582 {
583 return 1;
584 }
585 if (updateInProgress)
586 {
587 return 0;
588 }
589 unitMaskedState = req;
590 unitEnabledState = !unitMaskedState;
591 unitRunningState = !unitMaskedState;
592 updatedFlag |=
593 (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
594 (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
595 (1 << static_cast<uint8_t>(UpdatedProp::runningState));
596 internalSet = true;
597 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
598 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
599 internalSet = false;
600 startServiceRestartTimer();
601 }
602 res = req;
603 return 1;
604 });
605
606 srvCfgIface->register_property(srvCfgPropEnabled, unitEnabledState,
607 [this](const bool& req, bool& res) {
608 if (!internalSet)
609 {
610#ifdef USB_CODE_UPDATE
611 if (baseUnitName == usbCodeUpdateUnitName)
612 {
Vernon Maueryba2c0832020-07-15 10:02:38 -0700613 if (unitMaskedState)
614 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800615 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700616 return -EINVAL;
617 }
618 unitEnabledState = req;
Patrick Williamsdfc72702023-05-10 07:51:18 -0500619 unitRunningState = req;
620 internalSet = true;
621 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
622 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
623 internalSet = false;
624 setUSBCodeUpdateState(unitEnabledState);
625 saveUSBCodeUpdateStateToFile(unitMaskedState, unitEnabledState);
626 res = req;
627 return 1;
Vernon Maueryba2c0832020-07-15 10:02:38 -0700628 }
Chicago Duan25a0f632021-11-11 16:32:07 +0800629#endif
Patrick Williamsdfc72702023-05-10 07:51:18 -0500630 if (req == res)
631 {
632 return 1;
633 }
634 if (updateInProgress)
635 {
636 return 0;
637 }
638 if (unitMaskedState)
639 { // block updating if masked
640 lg2::error("Invalid value specified");
641 return -EINVAL;
642 }
643 unitEnabledState = req;
644 updatedFlag |= (1
645 << static_cast<uint8_t>(UpdatedProp::enabledState));
646 startServiceRestartTimer();
647 }
648 res = req;
649 return 1;
650 });
651
652 srvCfgIface->register_property(srvCfgPropRunning, unitRunningState,
653 [this](const bool& req, bool& res) {
654 if (!internalSet)
655 {
656#ifdef USB_CODE_UPDATE
657 if (baseUnitName == usbCodeUpdateUnitName)
658 {
Vernon Maueryba2c0832020-07-15 10:02:38 -0700659 if (unitMaskedState)
660 { // block updating if masked
George Liucb267c82022-01-05 17:53:28 +0800661 lg2::error("Invalid value specified");
Vernon Maueryba2c0832020-07-15 10:02:38 -0700662 return -EINVAL;
663 }
Patrick Williamsdfc72702023-05-10 07:51:18 -0500664 unitEnabledState = req;
Vernon Maueryba2c0832020-07-15 10:02:38 -0700665 unitRunningState = req;
Patrick Williamsdfc72702023-05-10 07:51:18 -0500666 internalSet = true;
667 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
668 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
669 internalSet = false;
670 setUSBCodeUpdateState(unitEnabledState);
671 saveUSBCodeUpdateStateToFile(unitMaskedState, unitEnabledState);
672 res = req;
673 return 1;
Vernon Maueryba2c0832020-07-15 10:02:38 -0700674 }
Patrick Williamsdfc72702023-05-10 07:51:18 -0500675#endif
676 if (req == res)
677 {
678 return 1;
679 }
680 if (updateInProgress)
681 {
682 return 0;
683 }
684 if (unitMaskedState)
685 { // block updating if masked
686 lg2::error("Invalid value specified");
687 return -EINVAL;
688 }
689 unitRunningState = req;
690 updatedFlag |= (1
691 << static_cast<uint8_t>(UpdatedProp::runningState));
692 startServiceRestartTimer();
693 }
694 res = req;
695 return 1;
696 });
Vernon Maueryba2c0832020-07-15 10:02:38 -0700697
698 srvCfgIface->initialize();
699 if (!socketObjectPath.empty())
700 {
701 sockAttrIface->initialize();
702 }
703 return;
704}
705
706} // namespace service
707} // namespace phosphor