Commit c0c8ee5ae9

daurnimator <quae@daurnimator.com>
2022-10-27 13:25:48
Add reboot syscall
Only linux for now
1 parent 0b99e5e
Changed files (2)
lib
lib/std/os/linux.zig
@@ -804,6 +804,63 @@ pub fn exit_group(status: i32) noreturn {
     unreachable;
 }
 
+/// flags for the `reboot' system call.
+pub const LINUX_REBOOT = struct {
+    /// First magic value required to use _reboot() system call.
+    pub const MAGIC1 = enum(u32) {
+        MAGIC1 = 0xfee1dead,
+        _,
+    };
+
+    /// Second magic value required to use _reboot() system call.
+    pub const MAGIC2 = enum(u32) {
+        MAGIC2 = 672274793,
+        MAGIC2A = 85072278,
+        MAGIC2B = 369367448,
+        MAGIC2C = 537993216,
+        _,
+    };
+
+    /// Commands accepted by the _reboot() system call.
+    pub const CMD = enum(u32) {
+        /// Restart system using default command and mode.
+        RESTART = 0x01234567,
+
+        /// Stop OS and give system control to ROM monitor, if any.
+        HALT = 0xCDEF0123,
+
+        /// Ctrl-Alt-Del sequence causes RESTART command.
+        CAD_ON = 0x89ABCDEF,
+
+        /// Ctrl-Alt-Del sequence sends SIGINT to init task.
+        CAD_OFF = 0x00000000,
+
+        /// Stop OS and remove all power from system, if possible.
+        POWER_OFF = 0x4321FEDC,
+
+        /// Restart system using given command string.
+        RESTART2 = 0xA1B2C3D4,
+
+        /// Suspend system using software suspend if compiled in.
+        SW_SUSPEND = 0xD000FCE2,
+
+        /// Restart system using a previously loaded Linux kernel
+        KEXEC = 0x45584543,
+
+        _,
+    };
+};
+
+pub fn reboot(magic: LINUX_REBOOT.MAGIC1, magic2: LINUX_REBOOT.MAGIC2, cmd: LINUX_REBOOT.CMD, arg: ?*const anyopaque) usize {
+    return std.os.linux.syscall4(
+        .reboot,
+        @enumToInt(magic),
+        @enumToInt(magic2),
+        @enumToInt(cmd),
+        @ptrToInt(arg),
+    );
+}
+
 pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
     return syscall3(.getrandom, @ptrToInt(buf), count, flags);
 }
lib/std/os.zig
@@ -366,6 +366,56 @@ pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void {
     }
 }
 
+pub const RebootError = error{
+    PermissionDenied,
+} || UnexpectedError;
+
+pub const RebootCommand = switch (builtin.os.tag) {
+    .linux => union(linux.LINUX_REBOOT.CMD) {
+        RESTART: void,
+        HALT: void,
+        CAD_ON: void,
+        CAD_OFF: void,
+        POWER_OFF: void,
+        RESTART2: [*:0]const u8,
+        SW_SUSPEND: void,
+        KEXEC: void,
+    },
+    else => @compileError("Unsupported OS"),
+};
+
+pub fn reboot(cmd: RebootCommand) RebootError!void {
+    switch (builtin.os.tag) {
+        .linux => {
+            switch (system.getErrno(linux.reboot(
+                .MAGIC1,
+                .MAGIC2,
+                @as(linux.LINUX_REBOOT.CMD, cmd),
+                switch (cmd) {
+                    .RESTART2 => |s| s,
+                    else => null,
+                },
+            ))) {
+                .SUCCESS => {},
+                .PERM => return error.PermissionDenied,
+                else => |err| return std.os.unexpectedErrno(err),
+            }
+            switch (cmd) {
+                .CAD_OFF => {},
+                .CAD_ON => {},
+                .SW_SUSPEND => {},
+
+                .HALT => unreachable,
+                .KEXEC => unreachable,
+                .POWER_OFF => unreachable,
+                .RESTART => unreachable,
+                .RESTART2 => unreachable,
+            }
+        },
+        else => @compileError("Unsupported OS"),
+    }
+}
+
 pub const GetRandomError = OpenError;
 
 /// Obtain a series of random bytes. These bytes can be used to seed user-space