1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "updater/hardware_fault_retry.h"
17 #include <unistd.h>
18 #include "init_reboot.h"
19 #include "log/log.h"
20 #include "misc_info/misc_info.h"
21 #include "updater/updater.h"
22 #include "updater/updater_const.h"
23 #include "utils.h"
24 #include "securec.h"
25
26 namespace Updater {
GetInstance()27 HardwareFaultRetry &HardwareFaultRetry::GetInstance()
28 {
29 static HardwareFaultRetry instance;
30 return instance;
31 }
32
HardwareFaultRetry()33 HardwareFaultRetry::HardwareFaultRetry()
34 {
35 RetryFunc rebootFunc = [this]() {
36 return this->RebootRetry();
37 };
38 RegisterFunc(VERIFY_FAILED_REBOOT, rebootFunc);
39 RegisterFunc(IO_FAILED_REBOOT, rebootFunc);
40 RegisterFunc(BLOCK_UPDATE_FAILED_REBOOT, rebootFunc);
41 }
42
RegisterFunc(const std::string & faultInfo,RetryFunc func)43 void HardwareFaultRetry::RegisterFunc(const std::string &faultInfo, RetryFunc func)
44 {
45 if (!retryMap_.emplace(faultInfo, func).second) {
46 LOG(ERROR) << "emplace: " << faultInfo.c_str() << " fail";
47 }
48 }
49
RegisterDefaultFunc(const std::string & faultInfo)50 void HardwareFaultRetry::RegisterDefaultFunc(const std::string &faultInfo)
51 {
52 if (!retryMap_.emplace(faultInfo, [this]() {
53 return this->RebootRetry();
54 }).second) {
55 LOG(ERROR) << "emplace: " << faultInfo.c_str() << " fail";
56 }
57 }
58
RemoveFunc(const std::string & faultInfo)59 void HardwareFaultRetry::RemoveFunc(const std::string &faultInfo)
60 {
61 if (retryMap_.erase(faultInfo) == 0) {
62 LOG(ERROR) << "erase " << faultInfo.c_str() << " fail";
63 }
64 }
65
DoRetryAction()66 void HardwareFaultRetry::DoRetryAction()
67 {
68 auto it = retryMap_.find(faultInfo_);
69 if (it == retryMap_.end() || it->second == nullptr) {
70 LOG(ERROR) << "GetRepair func for: " << faultInfo_.c_str() << " fail";
71 return;
72 }
73 return (it->second)();
74 }
75
SetFaultInfo(const std::string & faultInfo)76 void HardwareFaultRetry::SetFaultInfo(const std::string &faultInfo)
77 {
78 faultInfo_ = faultInfo;
79 }
80
SetRetryCount(const uint32_t count)81 void HardwareFaultRetry::SetRetryCount(const uint32_t count)
82 {
83 retryCount_ = count;
84 }
85
SetEffectiveValue(bool value)86 void HardwareFaultRetry::SetEffectiveValue(bool value)
87 {
88 effective_ = value;
89 }
90
SetRebootCmd(const std::string & rebootCmd)91 void HardwareFaultRetry::SetRebootCmd(const std::string &rebootCmd)
92 {
93 rebootCmd_ = rebootCmd;
94 }
95
IsRetry(void)96 bool HardwareFaultRetry::IsRetry(void)
97 {
98 return isRetry_;
99 }
100
RebootRetry()101 void HardwareFaultRetry::RebootRetry()
102 {
103 if (!effective_) {
104 LOG(WARNING) << "Special scenarios do not take effect, not need retry.";
105 return;
106 }
107 if (retryCount_ >= MAX_RETRY_COUNT) {
108 LOG(INFO) << "retry more than 3 times, no need retry";
109 return;
110 }
111 LOG(INFO) << "enter into reboot retry";
112 Utils::AddUpdateInfoToMisc("retry_count", retryCount_ + 1);
113 Utils::SetFaultInfoToMisc(faultInfo_);
114 isRetry_ = true;
115
116 PostUpdater(false);
117 sync();
118 #ifndef UPDATER_UT
119 if (rebootCmd_.empty()) {
120 DoReboot("updater:Updater fault retry");
121 } else {
122 DoReboot(rebootCmd_.c_str());
123 }
124 while (true) {
125 pause();
126 }
127 #endif
128 }
129 } // Updater
130