1 /*
2 * Copyright (c) 2022 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 <unistd.h>
17 #include <linux/reboot.h>
18 #include <sys/reboot.h>
19 #include <sys/syscall.h>
20
21 #include "reboot_adp.h"
22 #include "init_cmdexecutor.h"
23 #include "init_module_engine.h"
24 #include "init_utils.h"
25 #include "plugin_adapter.h"
26 #include "securec.h"
27
28 #define BUFF_SIZE 256
29
DoRoot_(const char * jobName,int type)30 PLUGIN_STATIC int DoRoot_(const char *jobName, int type)
31 {
32 // by job to stop service and unmount
33 if (jobName != NULL) {
34 DoJobNow(jobName);
35 }
36 #ifndef STARTUP_INIT_TEST
37 return reboot(type);
38 #else
39 return 0;
40 #endif
41 }
42
DoReboot(int id,const char * name,int argc,const char ** argv)43 static int DoReboot(int id, const char *name, int argc, const char **argv)
44 {
45 UNUSED(id);
46 UNUSED(name);
47 UNUSED(argc);
48 UNUSED(argv);
49 // clear misc
50 (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL);
51 return DoRoot_("reboot", RB_AUTOBOOT);
52 }
53
DoRebootPanic(int id,const char * name,int argc,const char ** argv)54 static int DoRebootPanic(int id, const char *name, int argc, const char **argv)
55 {
56 UNUSED(id);
57 char str[BUFF_SIZE] = {0};
58 int ret = sprintf_s(str, sizeof(str) - 1, "panic caused by %s:", name);
59 if (ret <= 0) {
60 PLUGIN_LOGW("DoRebootPanic sprintf_s name %s failed!", name);
61 }
62
63 int len = ret > 0 ? (sizeof(str) - ret) : sizeof(str);
64 char *tmp = str + (sizeof(str) - len);
65 for (int i = 0; i < argc; ++i) {
66 ret = sprintf_s(tmp, len - 1, " %s", argv[i]);
67 if (ret <= 0) {
68 PLUGIN_LOGW("DoRebootPanic sprintf_s arg %s failed!", argv[i]);
69 break;
70 } else {
71 len -= ret;
72 tmp += ret;
73 }
74 }
75 PLUGIN_LOGI("DoRebootPanic %s", str);
76 if (InRescueMode() == 0) {
77 PLUGIN_LOGI("Don't panic in resuce mode!");
78 return 0;
79 }
80 // clear misc
81 (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL);
82 DoJobNow("reboot");
83 #ifndef STARTUP_INIT_TEST
84 FILE *panic = fopen("/proc/sysrq-trigger", "wb");
85 if (panic == NULL) {
86 return reboot(RB_AUTOBOOT);
87 }
88 if (fwrite((void *)"c", 1, 1, panic) != 1) {
89 (void)fclose(panic);
90 PLUGIN_LOGI("fwrite to panic failed");
91 return -1;
92 }
93 (void)fclose(panic);
94 #endif
95 return 0;
96 }
97
DoRebootShutdown(int id,const char * name,int argc,const char ** argv)98 PLUGIN_STATIC int DoRebootShutdown(int id, const char *name, int argc, const char **argv)
99 {
100 UNUSED(id);
101 UNUSED(name);
102 UNUSED(argc);
103 UNUSED(argv);
104 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
105 // clear misc
106 (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL);
107 const size_t len = strlen("reboot,");
108 const char *cmd = strstr(argv[0], "reboot,");
109 if (cmd != NULL && strlen(cmd) > len) {
110 PLUGIN_LOGI("DoRebootShutdown argv %s", cmd + len);
111 // by job to stop service and unmount
112 DoJobNow("reboot");
113 #ifndef STARTUP_INIT_TEST
114 return syscall(__NR_reboot,
115 LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, cmd + len);
116 #else
117 return 0;
118 #endif
119 }
120 return DoRoot_("reboot", RB_POWER_OFF);
121 }
122
DoRebootUpdater(int id,const char * name,int argc,const char ** argv)123 static int DoRebootUpdater(int id, const char *name, int argc, const char **argv)
124 {
125 UNUSED(id);
126 PLUGIN_LOGI("DoRebootUpdater argc %d %s", argc, name);
127 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
128 PLUGIN_LOGI("DoRebootUpdater argv %s", argv[0]);
129 int ret = UpdateMiscMessage(argv[0], "updater", "updater:", "boot_updater");
130 if (ret == 0) {
131 return DoRoot_("reboot", RB_AUTOBOOT);
132 }
133 return ret;
134 }
135
DoRebootFlashed(int id,const char * name,int argc,const char ** argv)136 PLUGIN_STATIC int DoRebootFlashed(int id, const char *name, int argc, const char **argv)
137 {
138 UNUSED(id);
139 PLUGIN_LOGI("DoRebootFlashed argc %d %s", argc, name);
140 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
141 PLUGIN_LOGI("DoRebootFlashd argv %s", argv[0]);
142 int ret = UpdateMiscMessage(argv[0], "flash", "flash:", "boot_flash");
143 if (ret == 0) {
144 return DoRoot_("reboot", RB_AUTOBOOT);
145 }
146 return ret;
147 }
148
DoRebootCharge(int id,const char * name,int argc,const char ** argv)149 PLUGIN_STATIC int DoRebootCharge(int id, const char *name, int argc, const char **argv)
150 {
151 UNUSED(id);
152 UNUSED(name);
153 UNUSED(argc);
154 UNUSED(argv);
155 int ret = UpdateMiscMessage(NULL, "charge", "charge:", "boot_charge");
156 if (ret == 0) {
157 return DoRoot_("reboot", RB_AUTOBOOT);
158 }
159 return ret;
160 }
161
DoRebootSuspend(int id,const char * name,int argc,const char ** argv)162 static int DoRebootSuspend(int id, const char *name, int argc, const char **argv)
163 {
164 UNUSED(id);
165 UNUSED(name);
166 UNUSED(argc);
167 UNUSED(argv);
168 return DoRoot_("suspend", RB_AUTOBOOT);
169 }
170
DoRebootOther(int id,const char * name,int argc,const char ** argv)171 PLUGIN_STATIC int DoRebootOther(int id, const char *name, int argc, const char **argv)
172 {
173 UNUSED(id);
174 UNUSED(name);
175 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter argc %d", argc);
176 const char *cmd = strstr(argv[0], "reboot,");
177 PLUGIN_CHECK(cmd != NULL, return -1, "Invalid parameter argc %s", argv[0]);
178 PLUGIN_LOGI("DoRebootOther argv %s", argv[0]);
179 DoJobNow("reboot");
180 #ifndef STARTUP_INIT_TEST
181 return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
182 LINUX_REBOOT_CMD_RESTART2, cmd + strlen("reboot,"));
183 #else
184 return 0;
185 #endif
186 }
187
RebootAdpInit(void)188 static void RebootAdpInit(void)
189 {
190 // add default reboot cmd
191 (void)AddCmdExecutor("reboot", DoReboot);
192 (void)AddCmdExecutor("reboot.other", DoRebootOther);
193 AddRebootCmdExecutor("shutdown", DoRebootShutdown);
194 AddRebootCmdExecutor("flashd", DoRebootFlashed);
195 AddRebootCmdExecutor("updater", DoRebootUpdater);
196 AddRebootCmdExecutor("charge", DoRebootCharge);
197 AddRebootCmdExecutor("suspend", DoRebootSuspend);
198 AddRebootCmdExecutor("panic", DoRebootPanic);
199 (void)AddCmdExecutor("panic", DoRebootPanic);
200 }
201
MODULE_CONSTRUCTOR(void)202 MODULE_CONSTRUCTOR(void)
203 {
204 PLUGIN_LOGI("Reboot adapter plug-in init now ...");
205 RebootAdpInit();
206 }
207
MODULE_DESTRUCTOR(void)208 MODULE_DESTRUCTOR(void)
209 {
210 PLUGIN_LOGI("Reboot adapter plug-in exit now ...");
211 }
212