const std = @import("std"); const os = std.os; const mtd_rw_ko = @embedFile("mtd-rw.ko"); const InitModuleError = error { ModuleSignatureMisformatted, TimeoutResolvingSymbol, BadAddress, ModuleSigInvalid, OutOfMemory, PermissionDenied, AlreadyLoaded, BadParams, InvalidModule, }; const DeleteModuleError = error { ModuleNotLive, BadAddress, ModuleNotFound, PermissionDenied, ModuleInUse, }; pub fn load() !void { try insmod(mtd_rw_ko, "i_want_a_brick=1"); } pub fn unload() void { rmmod("mtd_rw", os.O_NONBLOCK) catch |err| { std.debug.warn("Failed to unload module: {}\n", .{err}); }; } pub fn insmod(buf: []const u8, args: [*:0]const u8) !void { const errno = os.linux.getErrno( os.linux.syscall3( os.linux.SYS_init_module, @ptrToInt(&buf[0]), buf.len, @ptrToInt(args))); switch (errno) { 0 => return, os.EEXIST => return, // It's not a failure if we have what we need os.EBADMSG => return InitModuleError.ModuleSignatureMisformatted, os.EBUSY => return InitModuleError.TimeoutResolvingSymbol, os.EFAULT => return InitModuleError.BadAddress, // os.ENOKEY => return InitModuleError.ModuleSigInvalid, os.ENOMEM => return InitModuleError.OutOfMemory, os.EPERM => return InitModuleError.PermissionDenied, os.EINVAL => return InitModuleError.BadParams, os.ENOEXEC => return InitModuleError.InvalidModule, else => |err| return os.unexpectedErrno(err), } } pub fn rmmod(mod_name: [*:0]const u8, flags: u32) !void { const errno = os.linux.getErrno( std.os.linux.syscall2( std.os.linux.SYS_delete_module, @ptrToInt(mod_name), flags)); switch (errno) { 0 => return, os.EBUSY => return DeleteModuleError.ModuleNotLive, os.EFAULT => return DeleteModuleError.BadAddress, os.ENOENT => return DeleteModuleError.ModuleNotFound, os.EPERM => return DeleteModuleError.PermissionDenied, os.EWOULDBLOCK => return DeleteModuleError.ModuleInUse, else => |err| return os.unexpectedErrno(err), } }