1 /* 2 * Copyright 2022, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 */ 5 #ifndef _UTIL_IOVEC_SUPPORT_H 6 #define _UTIL_IOVEC_SUPPORT_H 7 8 9 #include <KernelExport.h> 10 11 12 typedef struct generic_io_vec { 13 generic_addr_t base; 14 generic_size_t length; 15 } generic_io_vec; 16 17 18 #ifdef _KERNEL_VM_VM_H 19 20 static inline status_t 21 generic_memcpy(generic_addr_t dest, bool destPhysical, generic_addr_t src, bool srcPhysical, 22 generic_size_t size, bool user = false) 23 { 24 if (!srcPhysical && !destPhysical) { 25 if (user) 26 return user_memcpy((void*)dest, (void*)src, size); 27 memcpy((void*)dest, (void*)src, size); 28 return B_OK; 29 } else if (destPhysical && !srcPhysical) { 30 return vm_memcpy_to_physical(dest, (const void*)src, size, user); 31 } else if (!destPhysical && srcPhysical) { 32 return vm_memcpy_from_physical((void*)dest, src, size, user); 33 } 34 35 panic("generic_memcpy: physical -> physical not supported!"); 36 return B_NOT_SUPPORTED; 37 } 38 39 #endif 40 41 42 #ifdef IS_USER_ADDRESS 43 44 /*! 45 * Copies an array of `iovec`s from userland. 46 * Callers must verify vecCount <= IOV_MAX and supply their own vecs buffer. 47 */ 48 static inline status_t 49 get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec* vecs, 50 bool permitNull = false) 51 { 52 if (vecCount == 0) 53 return B_BAD_VALUE; 54 55 if (!IS_USER_ADDRESS(userVecs)) 56 return B_BAD_ADDRESS; 57 58 if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) 59 return B_BAD_ADDRESS; 60 61 size_t total = 0; 62 for (size_t i = 0; i < vecCount; i++) { 63 if (permitNull && vecs[i].iov_base == NULL) 64 continue; 65 if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) { 66 return B_BAD_ADDRESS; 67 } 68 if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) { 69 return B_BAD_VALUE; 70 } 71 total += vecs[i].iov_len; 72 } 73 74 return B_OK; 75 } 76 77 #endif 78 79 80 #endif // _UTIL_IOVEC_SUPPORT_H 81