starnix_syscalls/
syscall_arg.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use starnix_uapi::device_type::DeviceType;
6use starnix_uapi::file_mode::FileMode;
7use starnix_uapi::signals::UncheckedSignal;
8use starnix_uapi::user_address::{MappingMultiArchUserRef, MultiArchFrom, UserAddress, UserRef};
9use starnix_uapi::user_value::UserValue;
10
11#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
12pub struct SyscallArg(u64);
13
14impl SyscallArg {
15    pub fn from_raw(raw: u64) -> Self {
16        Self(raw)
17    }
18
19    pub fn raw(&self) -> u64 {
20        self.0
21    }
22}
23
24impl From<UserAddress> for SyscallArg {
25    fn from(value: UserAddress) -> Self {
26        Self::from_raw(value.ptr() as u64)
27    }
28}
29
30impl From<u64> for SyscallArg {
31    fn from(value: u64) -> Self {
32        Self::from_raw(value)
33    }
34}
35
36impl From<usize> for SyscallArg {
37    fn from(value: usize) -> Self {
38        Self::from_raw(value as u64)
39    }
40}
41
42impl From<UserValue<u64>> for SyscallArg {
43    fn from(value: UserValue<u64>) -> Self {
44        Self::from_raw(value.raw())
45    }
46}
47
48impl From<UserValue<usize>> for SyscallArg {
49    fn from(value: UserValue<usize>) -> Self {
50        Self::from_raw(value.raw() as u64)
51    }
52}
53
54impl From<bool> for SyscallArg {
55    fn from(value: bool) -> Self {
56        Self::from_raw(if value { 1 } else { 0 })
57    }
58}
59
60impl std::fmt::LowerHex for SyscallArg {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        std::fmt::LowerHex::fmt(&self.0, f)
63    }
64}
65
66macro_rules! impl_from_syscall_arg {
67    { for $ty:ty: $arg:ident => $($body:tt)* } => {
68        impl From<SyscallArg> for $ty {
69            fn from($arg: SyscallArg) -> Self { $($body)* }
70        }
71    }
72}
73
74impl_from_syscall_arg! { for bool: arg => arg.raw() != 0 }
75impl_from_syscall_arg! { for i32: arg => arg.raw() as Self }
76impl_from_syscall_arg! { for i64: arg => arg.raw() as Self }
77impl_from_syscall_arg! { for u32: arg => arg.raw() as Self }
78impl_from_syscall_arg! { for usize: arg => arg.raw() as Self }
79impl_from_syscall_arg! { for u64: arg => arg.raw() as Self }
80impl_from_syscall_arg! { for UserValue<i32>: arg => Self::from_raw(arg.raw() as i32) }
81impl_from_syscall_arg! { for UserValue<i64>: arg => Self::from_raw(arg.raw() as i64) }
82impl_from_syscall_arg! { for UserValue<u32>: arg => Self::from_raw(arg.raw() as u32) }
83impl_from_syscall_arg! { for UserValue<usize>: arg => Self::from_raw(arg.raw() as usize) }
84impl_from_syscall_arg! { for UserValue<u64>: arg => Self::from_raw(arg.raw() as u64) }
85impl_from_syscall_arg! { for UserAddress: arg => Self::from(arg.raw()) }
86
87impl_from_syscall_arg! { for FileMode: arg => Self::from_bits(arg.raw() as u32) }
88impl_from_syscall_arg! { for DeviceType: arg => Self::from_bits(arg.raw()) }
89impl_from_syscall_arg! { for UncheckedSignal: arg => Self::new(arg.raw()) }
90
91impl<T> From<SyscallArg> for UserRef<T> {
92    fn from(arg: SyscallArg) -> UserRef<T> {
93        Self::new(arg.into())
94    }
95}
96
97impl<T, T64, T32> MultiArchFrom<SyscallArg> for MappingMultiArchUserRef<T, T64, T32> {
98    fn from_64(value: SyscallArg) -> Self {
99        Self::from(UserRef::<T64>::from(value))
100    }
101    fn from_32(value: SyscallArg) -> Self {
102        Self::from_32(UserRef::<T32>::from(value))
103    }
104}