100f1e7c5SAugustin Cavalier /* 200f1e7c5SAugustin Cavalier * Copyright 2022, Haiku, Inc. All rights reserved. 300f1e7c5SAugustin Cavalier * Distributed under the terms of the MIT license. 400f1e7c5SAugustin Cavalier */ 500f1e7c5SAugustin Cavalier #ifndef _UTIL_IOVEC_SUPPORT_H 600f1e7c5SAugustin Cavalier #define _UTIL_IOVEC_SUPPORT_H 700f1e7c5SAugustin Cavalier 800f1e7c5SAugustin Cavalier 900f1e7c5SAugustin Cavalier #include <KernelExport.h> 1000f1e7c5SAugustin Cavalier 1100f1e7c5SAugustin Cavalier 1265cdc13eSAugustin Cavalier typedef struct generic_io_vec { 1365cdc13eSAugustin Cavalier generic_addr_t base; 1465cdc13eSAugustin Cavalier generic_size_t length; 1565cdc13eSAugustin Cavalier } generic_io_vec; 1665cdc13eSAugustin Cavalier 1765cdc13eSAugustin Cavalier 18*55a46882SAugustin Cavalier #ifdef _KERNEL_VM_VM_H 19*55a46882SAugustin Cavalier 20*55a46882SAugustin Cavalier static inline status_t 21*55a46882SAugustin Cavalier generic_memcpy(generic_addr_t dest, bool destPhysical, generic_addr_t src, bool srcPhysical, 22*55a46882SAugustin Cavalier generic_size_t size, bool user = false) 23*55a46882SAugustin Cavalier { 24*55a46882SAugustin Cavalier if (!srcPhysical && !destPhysical) { 25*55a46882SAugustin Cavalier if (user) 26*55a46882SAugustin Cavalier return user_memcpy((void*)dest, (void*)src, size); 27*55a46882SAugustin Cavalier memcpy((void*)dest, (void*)src, size); 28*55a46882SAugustin Cavalier return B_OK; 29*55a46882SAugustin Cavalier } else if (destPhysical && !srcPhysical) { 30*55a46882SAugustin Cavalier return vm_memcpy_to_physical(dest, (const void*)src, size, user); 31*55a46882SAugustin Cavalier } else if (!destPhysical && srcPhysical) { 32*55a46882SAugustin Cavalier return vm_memcpy_from_physical((void*)dest, src, size, user); 33*55a46882SAugustin Cavalier } 34*55a46882SAugustin Cavalier 35*55a46882SAugustin Cavalier panic("generic_memcpy: physical -> physical not supported!"); 36*55a46882SAugustin Cavalier return B_NOT_SUPPORTED; 37*55a46882SAugustin Cavalier } 38*55a46882SAugustin Cavalier 39*55a46882SAugustin Cavalier #endif 40*55a46882SAugustin Cavalier 41*55a46882SAugustin Cavalier 4265cdc13eSAugustin Cavalier #ifdef IS_USER_ADDRESS 43*55a46882SAugustin Cavalier 4400f1e7c5SAugustin Cavalier static inline status_t 4500f1e7c5SAugustin Cavalier get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs, 4600f1e7c5SAugustin Cavalier bool permitNull = false) 4700f1e7c5SAugustin Cavalier { 4800f1e7c5SAugustin Cavalier // prevent integer overflow 49013719cfSJérôme Duval if (vecCount > IOV_MAX || vecCount == 0) 5000f1e7c5SAugustin Cavalier return B_BAD_VALUE; 5100f1e7c5SAugustin Cavalier 5200f1e7c5SAugustin Cavalier if (!IS_USER_ADDRESS(userVecs)) 5300f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 5400f1e7c5SAugustin Cavalier 5500f1e7c5SAugustin Cavalier vecs = (iovec*)malloc(sizeof(iovec) * vecCount); 5600f1e7c5SAugustin Cavalier if (vecs == NULL) 5700f1e7c5SAugustin Cavalier return B_NO_MEMORY; 5800f1e7c5SAugustin Cavalier 59013719cfSJérôme Duval if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) { 60013719cfSJérôme Duval free(vecs); 6100f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 62013719cfSJérôme Duval } 6300f1e7c5SAugustin Cavalier 64013719cfSJérôme Duval size_t total = 0; 6500f1e7c5SAugustin Cavalier for (size_t i = 0; i < vecCount; i++) { 6600f1e7c5SAugustin Cavalier if (permitNull && vecs[i].iov_base == NULL) 6700f1e7c5SAugustin Cavalier continue; 68013719cfSJérôme Duval if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) { 69013719cfSJérôme Duval free(vecs); 7000f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 7100f1e7c5SAugustin Cavalier } 72013719cfSJérôme Duval if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) { 73013719cfSJérôme Duval free(vecs); 74013719cfSJérôme Duval return B_BAD_VALUE; 75013719cfSJérôme Duval } 76013719cfSJérôme Duval total += vecs[i].iov_len; 77013719cfSJérôme Duval } 7800f1e7c5SAugustin Cavalier 7900f1e7c5SAugustin Cavalier return B_OK; 8000f1e7c5SAugustin Cavalier } 81*55a46882SAugustin Cavalier 8265cdc13eSAugustin Cavalier #endif 8300f1e7c5SAugustin Cavalier 8400f1e7c5SAugustin Cavalier 8500f1e7c5SAugustin Cavalier #endif // _UTIL_IOVEC_SUPPORT_H 86