diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index f91cd54f..1323906b 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -111,6 +111,8 @@ namespace Kernel BAN::ErrorOr sys_sync(bool should_block); + BAN::ErrorOr sys_poweroff(int command); + BAN::ErrorOr mount(BAN::StringView source, BAN::StringView target); BAN::ErrorOr sys_read_dir_entries(int fd, DirectoryEntryList* buffer, size_t buffer_size); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 76c6a333..1c196819 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -14,8 +14,11 @@ #include #include +#include + #include #include +#include #include #include @@ -773,6 +776,33 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_poweroff(int command) + { + if (command != POWEROFF_REBOOT && command != POWEROFF_SHUTDOWN) + return BAN::Error::from_errno(EINVAL); + + // FIXME: gracefully kill all processes + + DevFileSystem::get().initiate_sync(true); + + lai_api_error_t error; + switch (command) + { + case POWEROFF_REBOOT: + error = lai_acpi_reset(); + break; + case POWEROFF_SHUTDOWN: + error = lai_enter_sleep(5); + break; + default: + ASSERT_NOT_REACHED(); + } + + // If we reach here, there was an error + dprintln("{}", lai_api_error_to_string(error)); + return BAN::Error::from_errno(EUNKNOWN); + } + BAN::ErrorOr Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 68bcd575..93f4c010 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -196,6 +196,9 @@ namespace Kernel case SYS_TTY_CTRL: ret = Process::current().sys_tty_ctrl((int)arg1, (int)arg2, (int)arg3); break; + case SYS_POWEROFF: + ret = Process::current().sys_poweroff((int)arg1); + break; default: dwarnln("Unknown syscall {}", syscall); break; diff --git a/libc/include/sys/banan-os.h b/libc/include/sys/banan-os.h index cb2a41cf..08fe6a38 100644 --- a/libc/include/sys/banan-os.h +++ b/libc/include/sys/banan-os.h @@ -11,8 +11,8 @@ __BEGIN_DECLS #define TTY_FLAG_ENABLE_OUTPUT 1 #define TTY_FLAG_ENABLE_INPUT 2 -#define POWER_SHUTDOWN 0 -#define POWER_REBOOT 1 +#define POWEROFF_SHUTDOWN 0 +#define POWEROFF_REBOOT 1 /* fildes: refers to valid tty device @@ -22,6 +22,7 @@ flags: bitwise or of TTY_FLAG_* definitions return value: 0 on success, -1 on failure and errno set to the error */ int tty_ctrl(int fildes, int command, int flags); +int poweroff(int command); __END_DECLS diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index a0f97ea1..797f8475 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -54,6 +54,7 @@ __BEGIN_DECLS #define SYS_MMAP 51 #define SYS_MUNMAP 52 #define SYS_TTY_CTRL 53 +#define SYS_POWEROFF 54 __END_DECLS diff --git a/libc/sys/banan-os.cpp b/libc/sys/banan-os.cpp index cc471928..d37d7060 100644 --- a/libc/sys/banan-os.cpp +++ b/libc/sys/banan-os.cpp @@ -6,3 +6,8 @@ int tty_ctrl(int fildes, int command, int flags) { return syscall(SYS_TTY_CTRL, fildes, command, flags); } + +int poweroff(int command) +{ + return syscall(SYS_POWEROFF, command); +} diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt index eddccd65..a704ceb1 100644 --- a/userspace/CMakeLists.txt +++ b/userspace/CMakeLists.txt @@ -9,6 +9,7 @@ set(USERSPACE_PROJECTS id init ls + poweroff Shell snake stat diff --git a/userspace/poweroff/CMakeLists.txt b/userspace/poweroff/CMakeLists.txt new file mode 100644 index 00000000..a9e65e2d --- /dev/null +++ b/userspace/poweroff/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.26) + +project(poweroff CXX) + +set(SOURCES + main.cpp +) + +add_executable(poweroff ${SOURCES}) +target_compile_options(poweroff PUBLIC -O2 -g) +target_link_libraries(poweroff PUBLIC libc) + +add_custom_target(poweroff-install + COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/poweroff ${BANAN_BIN}/ + DEPENDS poweroff + USES_TERMINAL +) diff --git a/userspace/poweroff/main.cpp b/userspace/poweroff/main.cpp new file mode 100644 index 00000000..797281bf --- /dev/null +++ b/userspace/poweroff/main.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +void usage(int ret, char* arg0) +{ + FILE* fout = (ret == 0) ? stdout : stderr; + fprintf(fout, "usage: %s [OPTIONS]...\n"); + fprintf(fout, " -s, --shutdown Shutdown the system (default)\n"); + fprintf(fout, " -r, --reboot Reboot the system\n"); + fprintf(fout, " -h, --help Show this message\n"); + exit(ret); +} + +int main(int argc, char** argv) +{ + int operation = POWEROFF_SHUTDOWN; + for (int i = 1; i < argc; i++) + { + if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--shutdown") == 0) + operation = POWEROFF_SHUTDOWN; + else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--reboot") == 0) + operation = POWEROFF_REBOOT; + else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) + usage(0, argv[0]); + else + usage(1, argv[0]); + } + + if (poweroff(operation) == -1) + { + perror("poweroff"); + return 1; + } + + return 0; +}