1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include <unistd.h> 17d9f0492fSopenharmony_ci#include <linux/reboot.h> 18d9f0492fSopenharmony_ci#include <sys/reboot.h> 19d9f0492fSopenharmony_ci#include <sys/syscall.h> 20d9f0492fSopenharmony_ci 21d9f0492fSopenharmony_ci#include "reboot_adp.h" 22d9f0492fSopenharmony_ci#include "init_cmdexecutor.h" 23d9f0492fSopenharmony_ci#include "init_module_engine.h" 24d9f0492fSopenharmony_ci#include "init_utils.h" 25d9f0492fSopenharmony_ci#include "plugin_adapter.h" 26d9f0492fSopenharmony_ci#include "securec.h" 27d9f0492fSopenharmony_ci 28d9f0492fSopenharmony_ci#define BUFF_SIZE 256 29d9f0492fSopenharmony_ci#define POWEROFF_REASON_DEV_PATH "/proc/poweroff_reason" 30d9f0492fSopenharmony_ci 31d9f0492fSopenharmony_cistatic int WritePowerOffReason(const char* reason) 32d9f0492fSopenharmony_ci{ 33d9f0492fSopenharmony_ci PLUGIN_CHECK(reason != NULL, return -1, "WritePowerOffReason: reason is NULL\n"); 34d9f0492fSopenharmony_ci PLUGIN_CHECK(access(POWEROFF_REASON_DEV_PATH, F_OK) == 0, return -1, 35d9f0492fSopenharmony_ci "WritePowerOffReason: access %s failed, errno = %d, %s\n", 36d9f0492fSopenharmony_ci POWEROFF_REASON_DEV_PATH, errno, strerror(errno)); 37d9f0492fSopenharmony_ci int fd = open(POWEROFF_REASON_DEV_PATH, O_RDWR); 38d9f0492fSopenharmony_ci PLUGIN_CHECK(fd > 0, return -1, "WritePowerOffReason: errno = %d, %s\n", errno, strerror(errno)); 39d9f0492fSopenharmony_ci int writeBytes = strlen(reason); 40d9f0492fSopenharmony_ci int ret = write(fd, reason, writeBytes); 41d9f0492fSopenharmony_ci PLUGIN_CHECK(ret == writeBytes, writeBytes = -1, "WritePowerOffReason: write poweroff reason failed\n"); 42d9f0492fSopenharmony_ci close(fd); 43d9f0492fSopenharmony_ci return writeBytes; 44d9f0492fSopenharmony_ci} 45d9f0492fSopenharmony_ci 46d9f0492fSopenharmony_cistatic void ParseRebootReason(const char *name, int argc, const char **argv) 47d9f0492fSopenharmony_ci{ 48d9f0492fSopenharmony_ci char str[BUFF_SIZE] = {0}; 49d9f0492fSopenharmony_ci int len = sizeof(str); 50d9f0492fSopenharmony_ci char *tmp = str; 51d9f0492fSopenharmony_ci int ret; 52d9f0492fSopenharmony_ci for (int i = 0; i < argc; i++) { 53d9f0492fSopenharmony_ci ret = sprintf_s(tmp, len - 1, "%s ", argv[i]); 54d9f0492fSopenharmony_ci if (ret <= 0) { 55d9f0492fSopenharmony_ci PLUGIN_LOGW("ParseRebootReason: sprintf_s arg %s failed!", argv[i]); 56d9f0492fSopenharmony_ci break; 57d9f0492fSopenharmony_ci } 58d9f0492fSopenharmony_ci len -= ret; 59d9f0492fSopenharmony_ci tmp += ret; 60d9f0492fSopenharmony_ci } 61d9f0492fSopenharmony_ci ret = WritePowerOffReason(str); 62d9f0492fSopenharmony_ci PLUGIN_CHECK(ret >= 0, return, "ParseRebootReason: write poweroff reason failed\n"); 63d9f0492fSopenharmony_ci} 64d9f0492fSopenharmony_ci 65d9f0492fSopenharmony_ciPLUGIN_STATIC int DoRoot_(const char *jobName, int type) 66d9f0492fSopenharmony_ci{ 67d9f0492fSopenharmony_ci // by job to stop service and unmount 68d9f0492fSopenharmony_ci if (jobName != NULL) { 69d9f0492fSopenharmony_ci DoJobNow(jobName); 70d9f0492fSopenharmony_ci } 71d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 72d9f0492fSopenharmony_ci return reboot(type); 73d9f0492fSopenharmony_ci#else 74d9f0492fSopenharmony_ci return 0; 75d9f0492fSopenharmony_ci#endif 76d9f0492fSopenharmony_ci} 77d9f0492fSopenharmony_ci 78d9f0492fSopenharmony_cistatic int DoReboot(int id, const char *name, int argc, const char **argv) 79d9f0492fSopenharmony_ci{ 80d9f0492fSopenharmony_ci UNUSED(id); 81d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 82d9f0492fSopenharmony_ci // clear misc 83d9f0492fSopenharmony_ci (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); 84d9f0492fSopenharmony_ci return DoRoot_("reboot", RB_AUTOBOOT); 85d9f0492fSopenharmony_ci} 86d9f0492fSopenharmony_ci 87d9f0492fSopenharmony_cistatic int DoRebootPanic(int id, const char *name, int argc, const char **argv) 88d9f0492fSopenharmony_ci{ 89d9f0492fSopenharmony_ci UNUSED(id); 90d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 91d9f0492fSopenharmony_ci if (InRescueMode() == 0) { 92d9f0492fSopenharmony_ci PLUGIN_LOGI("Don't panic in resuce mode!"); 93d9f0492fSopenharmony_ci return 0; 94d9f0492fSopenharmony_ci } 95d9f0492fSopenharmony_ci // clear misc 96d9f0492fSopenharmony_ci (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); 97d9f0492fSopenharmony_ci DoJobNow("reboot"); 98d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 99d9f0492fSopenharmony_ci FILE *panic = fopen("/proc/sysrq-trigger", "wb"); 100d9f0492fSopenharmony_ci if (panic == NULL) { 101d9f0492fSopenharmony_ci return reboot(RB_AUTOBOOT); 102d9f0492fSopenharmony_ci } 103d9f0492fSopenharmony_ci if (fwrite((void *)"c", 1, 1, panic) != 1) { 104d9f0492fSopenharmony_ci (void)fclose(panic); 105d9f0492fSopenharmony_ci PLUGIN_LOGI("fwrite to panic failed"); 106d9f0492fSopenharmony_ci return -1; 107d9f0492fSopenharmony_ci } 108d9f0492fSopenharmony_ci (void)fclose(panic); 109d9f0492fSopenharmony_ci#endif 110d9f0492fSopenharmony_ci return 0; 111d9f0492fSopenharmony_ci} 112d9f0492fSopenharmony_ci 113d9f0492fSopenharmony_ciPLUGIN_STATIC int DoRebootShutdown(int id, const char *name, int argc, const char **argv) 114d9f0492fSopenharmony_ci{ 115d9f0492fSopenharmony_ci UNUSED(id); 116d9f0492fSopenharmony_ci PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 117d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 118d9f0492fSopenharmony_ci // clear misc 119d9f0492fSopenharmony_ci (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); 120d9f0492fSopenharmony_ci const size_t len = strlen("reboot,"); 121d9f0492fSopenharmony_ci const char *cmd = strstr(argv[0], "reboot,"); 122d9f0492fSopenharmony_ci if (cmd != NULL && strlen(cmd) > len) { 123d9f0492fSopenharmony_ci PLUGIN_LOGI("DoRebootShutdown argv %s", cmd + len); 124d9f0492fSopenharmony_ci // by job to stop service and unmount 125d9f0492fSopenharmony_ci DoJobNow("reboot"); 126d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 127d9f0492fSopenharmony_ci return syscall(__NR_reboot, 128d9f0492fSopenharmony_ci LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, cmd + len); 129d9f0492fSopenharmony_ci#else 130d9f0492fSopenharmony_ci return 0; 131d9f0492fSopenharmony_ci#endif 132d9f0492fSopenharmony_ci } 133d9f0492fSopenharmony_ci return DoRoot_("reboot", RB_POWER_OFF); 134d9f0492fSopenharmony_ci} 135d9f0492fSopenharmony_ci 136d9f0492fSopenharmony_cistatic int DoRebootUpdater(int id, const char *name, int argc, const char **argv) 137d9f0492fSopenharmony_ci{ 138d9f0492fSopenharmony_ci UNUSED(id); 139d9f0492fSopenharmony_ci PLUGIN_LOGI("DoRebootUpdater argc %d %s", argc, name); 140d9f0492fSopenharmony_ci PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 141d9f0492fSopenharmony_ci PLUGIN_LOGI("DoRebootUpdater argv %s", argv[0]); 142d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 143d9f0492fSopenharmony_ci int ret = UpdateMiscMessage(argv[0], "updater", "updater:", "boot_updater"); 144d9f0492fSopenharmony_ci if (ret == 0) { 145d9f0492fSopenharmony_ci return DoRoot_("reboot", RB_AUTOBOOT); 146d9f0492fSopenharmony_ci } 147d9f0492fSopenharmony_ci return ret; 148d9f0492fSopenharmony_ci} 149d9f0492fSopenharmony_ci 150d9f0492fSopenharmony_ciPLUGIN_STATIC int DoRebootFlashed(int id, const char *name, int argc, const char **argv) 151d9f0492fSopenharmony_ci{ 152d9f0492fSopenharmony_ci UNUSED(id); 153d9f0492fSopenharmony_ci PLUGIN_LOGI("DoRebootFlashed argc %d %s", argc, name); 154d9f0492fSopenharmony_ci PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 155d9f0492fSopenharmony_ci PLUGIN_LOGI("DoRebootFlashd argv %s", argv[0]); 156d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 157d9f0492fSopenharmony_ci int ret = UpdateMiscMessage(argv[0], "flash", "flash:", "boot_flash"); 158d9f0492fSopenharmony_ci if (ret == 0) { 159d9f0492fSopenharmony_ci return DoRoot_("reboot", RB_AUTOBOOT); 160d9f0492fSopenharmony_ci } 161d9f0492fSopenharmony_ci return ret; 162d9f0492fSopenharmony_ci} 163d9f0492fSopenharmony_ci 164d9f0492fSopenharmony_ciPLUGIN_STATIC int DoRebootCharge(int id, const char *name, int argc, const char **argv) 165d9f0492fSopenharmony_ci{ 166d9f0492fSopenharmony_ci UNUSED(id); 167d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 168d9f0492fSopenharmony_ci int ret = UpdateMiscMessage(NULL, "charge", "charge:", "boot_charge"); 169d9f0492fSopenharmony_ci if (ret == 0) { 170d9f0492fSopenharmony_ci return DoRoot_("reboot", RB_AUTOBOOT); 171d9f0492fSopenharmony_ci } 172d9f0492fSopenharmony_ci return ret; 173d9f0492fSopenharmony_ci} 174d9f0492fSopenharmony_ci 175d9f0492fSopenharmony_cistatic int DoRebootSuspend(int id, const char *name, int argc, const char **argv) 176d9f0492fSopenharmony_ci{ 177d9f0492fSopenharmony_ci UNUSED(id); 178d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 179d9f0492fSopenharmony_ci return DoRoot_("suspend", RB_AUTOBOOT); 180d9f0492fSopenharmony_ci} 181d9f0492fSopenharmony_ci 182d9f0492fSopenharmony_ciPLUGIN_STATIC int DoRebootOther(int id, const char *name, int argc, const char **argv) 183d9f0492fSopenharmony_ci{ 184d9f0492fSopenharmony_ci UNUSED(id); 185d9f0492fSopenharmony_ci PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter argc %d", argc); 186d9f0492fSopenharmony_ci const char *cmd = strstr(argv[0], "reboot,"); 187d9f0492fSopenharmony_ci PLUGIN_CHECK(cmd != NULL, return -1, "Invalid parameter argc %s", argv[0]); 188d9f0492fSopenharmony_ci PLUGIN_LOGI("DoRebootOther argv %s", argv[0]); 189d9f0492fSopenharmony_ci ParseRebootReason(name, argc, argv); 190d9f0492fSopenharmony_ci // clear misc 191d9f0492fSopenharmony_ci (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); 192d9f0492fSopenharmony_ci DoJobNow("reboot"); 193d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 194d9f0492fSopenharmony_ci return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 195d9f0492fSopenharmony_ci LINUX_REBOOT_CMD_RESTART2, cmd + strlen("reboot,")); 196d9f0492fSopenharmony_ci#else 197d9f0492fSopenharmony_ci return 0; 198d9f0492fSopenharmony_ci#endif 199d9f0492fSopenharmony_ci} 200d9f0492fSopenharmony_ci 201d9f0492fSopenharmony_cistatic void RebootAdpInit(void) 202d9f0492fSopenharmony_ci{ 203d9f0492fSopenharmony_ci // add default reboot cmd 204d9f0492fSopenharmony_ci (void)AddCmdExecutor("reboot", DoReboot); 205d9f0492fSopenharmony_ci (void)AddCmdExecutor("reboot.other", DoRebootOther); 206d9f0492fSopenharmony_ci AddRebootCmdExecutor("shutdown", DoRebootShutdown); 207d9f0492fSopenharmony_ci AddRebootCmdExecutor("flashd", DoRebootFlashed); 208d9f0492fSopenharmony_ci AddRebootCmdExecutor("updater", DoRebootUpdater); 209d9f0492fSopenharmony_ci AddRebootCmdExecutor("charge", DoRebootCharge); 210d9f0492fSopenharmony_ci AddRebootCmdExecutor("suspend", DoRebootSuspend); 211d9f0492fSopenharmony_ci AddRebootCmdExecutor("panic", DoRebootPanic); 212d9f0492fSopenharmony_ci (void)AddCmdExecutor("panic", DoRebootPanic); 213d9f0492fSopenharmony_ci} 214d9f0492fSopenharmony_ci 215d9f0492fSopenharmony_ciMODULE_CONSTRUCTOR(void) 216d9f0492fSopenharmony_ci{ 217d9f0492fSopenharmony_ci PLUGIN_LOGI("Reboot adapter plug-in init now ..."); 218d9f0492fSopenharmony_ci RebootAdpInit(); 219d9f0492fSopenharmony_ci} 220d9f0492fSopenharmony_ci 221d9f0492fSopenharmony_ciMODULE_DESTRUCTOR(void) 222d9f0492fSopenharmony_ci{ 223d9f0492fSopenharmony_ci PLUGIN_LOGI("Reboot adapter plug-in exit now ..."); 224d9f0492fSopenharmony_ci} 225