blob: 4a13a4afdb1e152768db30f28c74aef773fafa6e [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use paste::paste;
use zerocopy::{AsBytes, FromBytes};
use crate::fs::FdNumber;
use crate::syscalls::*;
use crate::uapi::*;
trait FromSyscallArg {
fn from_arg(arg: u64) -> Self;
}
impl FromSyscallArg for i32 {
fn from_arg(arg: u64) -> i32 {
arg as i32
}
}
impl FromSyscallArg for u32 {
fn from_arg(arg: u64) -> u32 {
arg as u32
}
}
impl FromSyscallArg for usize {
fn from_arg(arg: u64) -> usize {
arg as usize
}
}
impl FromSyscallArg for u64 {
fn from_arg(arg: u64) -> u64 {
arg
}
}
impl FromSyscallArg for UserAddress {
fn from_arg(arg: u64) -> UserAddress {
UserAddress::from(arg)
}
}
impl<T: AsBytes + FromBytes> FromSyscallArg for UserRef<T> {
fn from_arg(arg: u64) -> UserRef<T> {
UserRef::<T>::new(UserAddress::from(arg))
}
}
impl FromSyscallArg for UserCString {
fn from_arg(arg: u64) -> UserCString {
UserCString::new(UserAddress::from(arg))
}
}
impl FromSyscallArg for FdNumber {
fn from_arg(arg: u64) -> FdNumber {
FdNumber::from_raw(arg as i32)
}
}
trait IntoSyscallArg<T> {
fn into_arg(self) -> T;
}
impl<T> IntoSyscallArg<T> for u64
where
T: FromSyscallArg,
{
fn into_arg(self) -> T {
T::from_arg(self)
}
}
macro_rules! syscall_match {
{
$ctx:ident; $syscall_number:ident; $args:ident;
$($call:ident [$num_args:tt],)*
} => {
paste! {
match $syscall_number as u32 {
$(crate::uapi::[<__NR_ $call>] => syscall_match!(@call $ctx; $args; [<sys_ $call>][$num_args]),)*
_ => sys_unknown($ctx, $syscall_number),
}
}
};
(@call $ctx:ident; $args:ident; $func:ident [0]) => ($func($ctx));
(@call $ctx:ident; $args:ident; $func:ident [1]) => ($func($ctx, $args.0.into_arg()));
(@call $ctx:ident; $args:ident; $func:ident [2]) => ($func($ctx, $args.0.into_arg(), $args.1.into_arg()));
(@call $ctx:ident; $args:ident; $func:ident [3]) => ($func($ctx, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg()));
(@call $ctx:ident; $args:ident; $func:ident [4]) => ($func($ctx, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg(), $args.3.into_arg()));
(@call $ctx:ident; $args:ident; $func:ident [5]) => ($func($ctx, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg(), $args.3.into_arg(), $args.4.into_arg()));
(@call $ctx:ident; $args:ident; $func:ident [6]) => ($func($ctx, $args.0.into_arg(), $args.1.into_arg(), $args.2.into_arg(), $args.3.into_arg(), $args.4.into_arg(), $args.5.into_arg()));
}
pub fn dispatch_syscall(
ctx: &mut SyscallContext<'_>,
syscall_number: u64,
args: (u64, u64, u64, u64, u64, u64),
) -> Result<SyscallResult, Errno> {
syscall_match! {
ctx; syscall_number; args;
access[2],
arch_prctl[2],
brk[1],
clock_gettime[2],
exit[1],
exit_group[1],
fcntl[3],
fstat[2],
fstatfs[2],
getcwd[2],
getegid[0],
geteuid[0],
getgid[0],
getpgid[1],
getpgrp[0],
getpid[0],
getppid[0],
getrandom[3],
gettid[0],
gettimeofday[2],
getuid[0],
ioctl[4],
mmap[6],
mprotect[3],
munmap[2],
openat[4],
prctl[5],
pread64[4],
readlink[3],
rt_sigprocmask[4],
sched_getaffinity[3],
sched_getscheduler[1],
sched_setaffinity[3],
set_tid_address[1],
sigaltstack[2],
uname[1],
write[3],
writev[3],
}
}