diff --git a/platform/debug.c b/platform/debug.c index cd41b26d4..7d2d1000a 100644 --- a/platform/debug.c +++ b/platform/debug.c @@ -6,9 +6,9 @@ * https://opensource.org/licenses/MIT */ +#include + #include -#include -#include /* Default implementation of panic time getc/putc. * Just calls through to the underlying dputc/dgetc implementation diff --git a/platform/include/platform.h b/platform/include/platform.h index 598a43b1a..78353e444 100644 --- a/platform/include/platform.h +++ b/platform/include/platform.h @@ -21,6 +21,8 @@ typedef enum { HALT_ACTION_SHUTDOWN, // Shutdown and power off. } platform_halt_action; +const char *platform_halt_action_string(platform_halt_action action); + typedef enum { HALT_REASON_UNKNOWN = 0, HALT_REASON_POR, // Cold-boot @@ -35,14 +37,7 @@ typedef enum { HALT_REASON_SW_UPDATE, // SW triggered reboot in order to begin firmware update } platform_halt_reason; -/* super early platform initialization, before almost everything */ -void platform_early_init(void); - -/* later init, after the kernel has come up */ -void platform_init(void); - -/* called by the arch init code to get the platform to set up any mmu mappings it may need */ -void platform_init_mmu_mappings(void); +const char *platform_halt_reason_string(platform_halt_reason reason); /* if the platform has knowledge of what caused the latest reboot, it can report * it to applications with this function. */ @@ -62,11 +57,30 @@ platform_halt_reason platform_get_reboot_reason(void); * reason, and then halt execution by turning off interrupts and spinning * forever. */ -void platform_halt(platform_halt_action suggested_action, +__WEAK void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) __NO_RETURN; +/* Default implementation of the above routine, which platforms can call with + * appropriate hooks to implement platform specific reboot and shutdown behavior. + */ +typedef void (*platform_reboot_hook)(void); +typedef void (*platform_shutdown_hook)(void); +void platform_halt_default(platform_halt_action suggested_action, + platform_halt_reason reason, + platform_reboot_hook prh, + platform_shutdown_hook psh) __NO_RETURN; + /* called during chain loading to make sure drivers and platform is put into a stopped state */ void platform_quiesce(void); +/* super early platform initialization, before almost everything */ +void platform_early_init(void); + +/* later init, after the kernel has come up */ +void platform_init(void); + +/* called by the arch init code to get the platform to set up any mmu mappings it may need */ +void platform_init_mmu_mappings(void); + __END_CDECLS diff --git a/platform/init.c b/platform/init.c index b3d1b65ea..9f36a3b00 100644 --- a/platform/init.c +++ b/platform/init.c @@ -5,9 +5,10 @@ * license that can be found in the LICENSE file or at * https://opensource.org/licenses/MIT */ +#include + #include #include -#include /* * default implementations of these routines, if the platform code diff --git a/platform/jh7110/platform.c b/platform/jh7110/platform.c index e72342f67..b48ae46f9 100644 --- a/platform/jh7110/platform.c +++ b/platform/jh7110/platform.c @@ -24,9 +24,6 @@ #include #endif #include -#if WITH_LIB_CONSOLE -#include -#endif #include "platform_p.h" @@ -82,35 +79,20 @@ void platform_init(void) { } -void platform_halt(platform_halt_action suggested_action, - platform_halt_reason reason) { - switch (suggested_action) { - case HALT_ACTION_SHUTDOWN: - dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason); - // try to use SBI as a cleaner way to stop - sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); - *power_reset_reg = 0x5555; - break; - case HALT_ACTION_REBOOT: - dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason); - sbi_system_reset(SBI_RESET_TYPE_WARM_REBOOT, SBI_RESET_REASON_NONE); - *power_reset_reg = 0x7777; - break; - case HALT_ACTION_HALT: -#if ENABLE_PANIC_SHELL - if (reason == HALT_REASON_SW_PANIC) { - dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason); - arch_disable_ints(); - panic_shell_start(); - } -#endif // ENABLE_PANIC_SHELL - dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); - break; - } +static void reboot_(void) { + sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE); + *power_reset_reg = 0x7777; +} + +static void shutdown_(void) { + // try to use sbi as a cleaner way to stop + sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); + *power_reset_reg = 0x5555; +} - arch_disable_ints(); - for (;;) - arch_idle(); +void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) { + // Use the default halt implementation using sbi as the reset and shutdown implementation. + platform_halt_default(suggested_action, reason, &reboot_, &shutdown_); } status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) { diff --git a/platform/pc/debug.c b/platform/pc/debug.c index 648cdc63c..61e09fe38 100644 --- a/platform/pc/debug.c +++ b/platform/pc/debug.c @@ -94,12 +94,3 @@ void platform_dputc(char c) { int platform_dgetc(char *c, bool wait) { return cbuf_read_char(&console_input_buf, c, wait); } - -void platform_halt(platform_halt_action suggested_action, - platform_halt_reason reason) { - for (;;) { - x86_cli(); - x86_hlt(); - } -} - diff --git a/platform/power.c b/platform/power.c index 24c7ed77d..de8a48b2e 100644 --- a/platform/power.c +++ b/platform/power.c @@ -12,32 +12,99 @@ #include #include #include -#include #if WITH_LIB_CONSOLE #include #endif -/* - * default implementations of these routines, if the platform code - * chooses not to implement. - */ -__WEAK void platform_halt(platform_halt_action suggested_action, - platform_halt_reason reason) { +// Default implementation of the system halt and reset function. Platforms may use +// this as a helper to implement the logic by passing in a few hooks to do the +// actual shutdown or reboot. +void platform_halt_default(platform_halt_action suggested_action, + platform_halt_reason reason, + platform_reboot_hook prh, + platform_shutdown_hook psh) { + const char *reason_string = platform_halt_reason_string(reason); + switch (suggested_action) { + case HALT_ACTION_SHUTDOWN: + if (psh) { + dprintf(ALWAYS, "Shutting down, reason '%s'\n", reason_string); + psh(); + } + break; + case HALT_ACTION_REBOOT: + if (prh) { + dprintf(ALWAYS, "Rebooting, reason '%s'\n", reason_string); + prh(); + } + break; + case HALT_ACTION_HALT: #if ENABLE_PANIC_SHELL - if (reason == HALT_REASON_SW_PANIC && suggested_action == HALT_ACTION_HALT) { - dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason); - arch_disable_ints(); - panic_shell_start(); - } + if (reason == HALT_REASON_SW_PANIC) { + dprintf(ALWAYS, "CRASH: starting debug shell, reason '%s'\n", reason_string); + arch_disable_ints(); + panic_shell_start(); + } #endif // ENABLE_PANIC_SHELL + break; + } - dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); + dprintf(ALWAYS, "HALT: spinning forever, reason '%s'\n", reason_string); arch_disable_ints(); for (;;) arch_idle(); } +// Default implementation of platform halt, which simply start the debug shell or spins forever. +__WEAK void platform_halt(platform_halt_action suggested_action, + platform_halt_reason reason) { + platform_halt_default(suggested_action, reason, NULL, NULL); +} + +__WEAK platform_halt_reason platform_get_reboot_reason(void) { + return HALT_REASON_UNKNOWN; +} + +const char *platform_halt_action_string(platform_halt_action action) { + switch(action) { + case HALT_ACTION_HALT: + return "halt"; + case HALT_ACTION_REBOOT: + return "reboot"; + case HALT_ACTION_SHUTDOWN: + return "shutdown"; + } + return "unknown"; +} + +const char *platform_halt_reason_string(platform_halt_reason reason) { + switch(reason) { + case HALT_REASON_UNKNOWN: + return "unknown"; + case HALT_REASON_POR: + return "power on reset"; + case HALT_REASON_HW_WATCHDOG: + return "hardware watchdog"; + case HALT_REASON_LOWVOLTAGE: + return "low voltage"; + case HALT_REASON_HIGHVOLTAGE: + return "high voltage"; + case HALT_REASON_THERMAL: + return "thermal"; + case HALT_REASON_OTHER_HW: + return "other hardware"; + case HALT_REASON_SW_RESET: + return "software reset"; + case HALT_REASON_SW_WATCHDOG: + return "software watchdog"; + case HALT_REASON_SW_PANIC: + return "software panic"; + case HALT_REASON_SW_UPDATE: + return "software update"; + } + return "unknown"; +} + static int cmd_reboot(int argc, const console_cmd_args *argv) { platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET); return 0; diff --git a/platform/qemu-virt-arm/debug.c b/platform/qemu-virt-arm/debug.c index 99679816a..f8be333c4 100644 --- a/platform/qemu-virt-arm/debug.c +++ b/platform/qemu-virt-arm/debug.c @@ -30,8 +30,8 @@ void platform_dputc(char c) { int platform_dgetc(char *c, bool wait) { int ret = uart_getc(DEBUG_UART, wait); - if (ret == -1) - return -1; + if (ret < 0) + return ret; *c = ret; return 0; } diff --git a/platform/qemu-virt-arm/platform.c b/platform/qemu-virt-arm/platform.c index c492c6753..1af6082c4 100644 --- a/platform/qemu-virt-arm/platform.c +++ b/platform/qemu-virt-arm/platform.c @@ -194,16 +194,6 @@ status_t platform_compute_msi_values(unsigned int vector, unsigned int cpu, bool } void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) { - switch (suggested_action) { - case HALT_ACTION_SHUTDOWN: - case HALT_ACTION_HALT: - psci_system_off(); - break; - case HALT_ACTION_REBOOT: - psci_system_reset(); - break; - } - dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); - arch_disable_ints(); - for (;;); + // Use the default halt implementation using psci as the reset and shutdown implementation. + platform_halt_default(suggested_action, reason, &psci_system_reset, &psci_system_off); } diff --git a/platform/qemu-virt-m68k/platform.c b/platform/qemu-virt-m68k/platform.c index 7f4d91075..bc1a78b2a 100644 --- a/platform/qemu-virt-m68k/platform.c +++ b/platform/qemu-virt-m68k/platform.c @@ -24,9 +24,6 @@ #else #include #endif -#if WITH_LIB_CONSOLE -#include -#endif #include "platform_p.h" @@ -119,33 +116,3 @@ void platform_init(void) { } #endif } - -#if 0 -void platform_halt(platform_halt_action suggested_action, - platform_halt_reason reason) { - switch (suggested_action) { - case HALT_ACTION_SHUTDOWN: - dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason); - *power_reset_reg = 0x5555; - break; - case HALT_ACTION_REBOOT: - dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason); - *power_reset_reg = 0x7777; - break; - case HALT_ACTION_HALT: -#if ENABLE_PANIC_SHELL - if (reason == HALT_REASON_SW_PANIC) { - dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason); - arch_disable_ints(); - panic_shell_start(); - } -#endif // ENABLE_PANIC_SHELL - dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); - break; - } - - arch_disable_ints(); - for (;;) - arch_idle(); -} -#endif diff --git a/platform/qemu-virt-riscv/platform.c b/platform/qemu-virt-riscv/platform.c index 459f0e5ba..2372fba7d 100644 --- a/platform/qemu-virt-riscv/platform.c +++ b/platform/qemu-virt-riscv/platform.c @@ -31,9 +31,6 @@ #else #include #endif -#if WITH_LIB_CONSOLE -#include -#endif #include "platform_p.h" @@ -123,39 +120,24 @@ void platform_init(void) { #endif } -void platform_halt(platform_halt_action suggested_action, - platform_halt_reason reason) { - switch (suggested_action) { - case HALT_ACTION_SHUTDOWN: - dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason); +static void reboot_(void) { #if RISCV_S_MODE - // try to use SBI as a cleaner way to stop - sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); + sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE); #endif - *power_reset_reg = 0x5555; - break; - case HALT_ACTION_REBOOT: - dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason); + *power_reset_reg = 0x7777; +} + +static void shutdown_(void) { #if RISCV_S_MODE - sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE); + // try to use sbi as a cleaner way to stop + sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); #endif - *power_reset_reg = 0x7777; - break; - case HALT_ACTION_HALT: -#if ENABLE_PANIC_SHELL - if (reason == HALT_REASON_SW_PANIC) { - dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason); - arch_disable_ints(); - panic_shell_start(); - } -#endif // ENABLE_PANIC_SHELL - dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); - break; - } + *power_reset_reg = 0x5555; +} - arch_disable_ints(); - for (;;) - arch_idle(); +void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) { + // Use the default halt implementation using sbi as the reset and shutdown implementation. + platform_halt_default(suggested_action, reason, &reboot_, &shutdown_); } status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) { diff --git a/platform/spacemit-k1/platform.c b/platform/spacemit-k1/platform.c index 49b3c9a62..ca587273b 100644 --- a/platform/spacemit-k1/platform.c +++ b/platform/spacemit-k1/platform.c @@ -24,9 +24,6 @@ #include #endif #include -#if WITH_LIB_CONSOLE -#include -#endif #include "platform_p.h" @@ -68,33 +65,22 @@ void platform_init(void) { uart_init(); } -void platform_halt(platform_halt_action suggested_action, - platform_halt_reason reason) { - switch (suggested_action) { - case HALT_ACTION_SHUTDOWN: - dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason); - // try to use SBI as a cleaner way to stop - sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); - break; - case HALT_ACTION_REBOOT: - dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason); - sbi_system_reset(SBI_RESET_TYPE_WARM_REBOOT, SBI_RESET_REASON_NONE); - break; - case HALT_ACTION_HALT: -#if ENABLE_PANIC_SHELL - if (reason == HALT_REASON_SW_PANIC) { - dprintf(ALWAYS, "CRASH: starting debug shell... (reason = %d)\n", reason); - arch_disable_ints(); - panic_shell_start(); - } -#endif // ENABLE_PANIC_SHELL - dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); - break; - } +static void reboot_(void) { +#if RISCV_S_MODE + sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE); +#endif +} + +static void shutdown_(void) { +#if RISCV_S_MODE + // try to use sbi as a cleaner way to stop + sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE); +#endif +} - arch_disable_ints(); - for (;;) - arch_idle(); +void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) { + // Use the default halt implementation using sbi as the reset and shutdown implementation. + platform_halt_default(suggested_action, reason, &reboot_, &shutdown_); } status_t platform_pci_int_to_vector(unsigned int pci_int, unsigned int *vector) {