xref: /haiku/headers/private/kernel/util/iovec_support.h (revision 4169a972eea20e94d1b318f0ae790b749f564fc1)
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