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
12typedef 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
20static inline status_t
21generic_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
44static inline status_t
45get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs,
46	bool permitNull = false)
47{
48	// prevent integer overflow
49	if (vecCount > IOV_MAX || vecCount == 0)
50		return B_BAD_VALUE;
51
52	if (!IS_USER_ADDRESS(userVecs))
53		return B_BAD_ADDRESS;
54
55	vecs = (iovec*)malloc(sizeof(iovec) * vecCount);
56	if (vecs == NULL)
57		return B_NO_MEMORY;
58
59	if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) {
60		free(vecs);
61		return B_BAD_ADDRESS;
62	}
63
64	size_t total = 0;
65	for (size_t i = 0; i < vecCount; i++) {
66		if (permitNull && vecs[i].iov_base == NULL)
67			continue;
68		if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) {
69			free(vecs);
70			return B_BAD_ADDRESS;
71		}
72		if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) {
73			free(vecs);
74			return B_BAD_VALUE;
75		}
76		total += vecs[i].iov_len;
77	}
78
79	return B_OK;
80}
81
82#endif
83
84
85#endif	// _UTIL_IOVEC_SUPPORT_H
86