1 /*
2  * Copyright (c) 2012 Google, Inc.
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/debug.h>
9 #include <lk/err.h>
10 #include <lk/compiler.h>
11 #include <lk/console_cmd.h>
12 #include <platform.h>
13 #include <platform/debug.h>
14 #include <kernel/thread.h>
15 
16 #if WITH_LIB_CONSOLE
17 #include <lib/console.h>
18 #endif
19 
20 // Default implementation of the system halt and reset function. Platforms may use
21 // this as a helper to implement the logic by passing in a few hooks to do the
22 // actual shutdown or reboot.
platform_halt_default(platform_halt_action suggested_action,platform_halt_reason reason,platform_reboot_hook prh,platform_shutdown_hook psh)23 void platform_halt_default(platform_halt_action suggested_action,
24                            platform_halt_reason reason,
25                            platform_reboot_hook prh,
26                            platform_shutdown_hook psh) {
27     const char *reason_string = platform_halt_reason_string(reason);
28     switch (suggested_action) {
29         case HALT_ACTION_SHUTDOWN:
30             if (psh) {
31                 dprintf(ALWAYS, "Shutting down, reason '%s'\n", reason_string);
32                 psh();
33             }
34             break;
35         case HALT_ACTION_REBOOT:
36             if (prh) {
37                 dprintf(ALWAYS, "Rebooting, reason '%s'\n", reason_string);
38                 prh();
39             }
40             break;
41         case HALT_ACTION_HALT:
42 #if ENABLE_PANIC_SHELL
43             if (reason == HALT_REASON_SW_PANIC) {
44                 dprintf(ALWAYS, "CRASH: starting debug shell, reason '%s'\n", reason_string);
45                 arch_disable_ints();
46                 panic_shell_start();
47             }
48 #endif  // ENABLE_PANIC_SHELL
49             break;
50     }
51 
52     dprintf(ALWAYS, "HALT: spinning forever, reason '%s'\n", reason_string);
53     arch_disable_ints();
54     for (;;)
55         arch_idle();
56 }
57 
58 // Default implementation of platform halt, which simply start the debug shell or spins forever.
platform_halt(platform_halt_action suggested_action,platform_halt_reason reason)59 __WEAK void platform_halt(platform_halt_action suggested_action,
60                           platform_halt_reason reason) {
61     platform_halt_default(suggested_action, reason, NULL, NULL);
62 }
63 
platform_get_reboot_reason(void)64 __WEAK platform_halt_reason platform_get_reboot_reason(void) {
65     return HALT_REASON_UNKNOWN;
66 }
67 
platform_halt_action_string(platform_halt_action action)68 const char *platform_halt_action_string(platform_halt_action action) {
69     switch(action) {
70         case HALT_ACTION_HALT:
71             return "halt";
72         case HALT_ACTION_REBOOT:
73             return "reboot";
74         case HALT_ACTION_SHUTDOWN:
75             return "shutdown";
76     }
77     return "unknown";
78 }
79 
platform_halt_reason_string(platform_halt_reason reason)80 const char *platform_halt_reason_string(platform_halt_reason reason) {
81     switch(reason) {
82         case HALT_REASON_UNKNOWN:
83             return "unknown";
84         case HALT_REASON_POR:
85             return "power on reset";
86         case HALT_REASON_HW_WATCHDOG:
87             return "hardware watchdog";
88         case HALT_REASON_LOWVOLTAGE:
89             return "low voltage";
90         case HALT_REASON_HIGHVOLTAGE:
91             return "high voltage";
92         case HALT_REASON_THERMAL:
93             return "thermal";
94         case HALT_REASON_OTHER_HW:
95             return "other hardware";
96         case HALT_REASON_SW_RESET:
97             return "software reset";
98         case HALT_REASON_SW_WATCHDOG:
99             return "software watchdog";
100         case HALT_REASON_SW_PANIC:
101             return "software panic";
102         case HALT_REASON_SW_UPDATE:
103             return "software update";
104     }
105     return "unknown";
106 }
107 
cmd_reboot(int argc,const console_cmd_args * argv)108 static int cmd_reboot(int argc, const console_cmd_args *argv) {
109     platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
110     return 0;
111 }
112 
cmd_poweroff(int argc,const console_cmd_args * argv)113 static int cmd_poweroff(int argc, const console_cmd_args *argv) {
114     platform_halt(HALT_ACTION_SHUTDOWN, HALT_REASON_SW_RESET);
115     return 0;
116 }
117 
118 STATIC_COMMAND_START
119 #if LK_DEBUGLEVEL > 1
120 STATIC_COMMAND("reboot", "soft reset", &cmd_reboot)
121 STATIC_COMMAND("poweroff", "powerdown", &cmd_poweroff)
122 #endif
123 STATIC_COMMAND_END(platform_power);
124