xref: /illumos-gate/usr/src/uts/intel/os/copy_subr.c (revision f0089e391b2bc4be2755f1a1b51fb4cd9b8f3988)
1*f0089e39SRichard Lowe /*
2*f0089e39SRichard Lowe  * CDDL HEADER START
3*f0089e39SRichard Lowe  *
4*f0089e39SRichard Lowe  * The contents of this file are subject to the terms of the
5*f0089e39SRichard Lowe  * Common Development and Distribution License, Version 1.0 only
6*f0089e39SRichard Lowe  * (the "License").  You may not use this file except in compliance
7*f0089e39SRichard Lowe  * with the License.
8*f0089e39SRichard Lowe  *
9*f0089e39SRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*f0089e39SRichard Lowe  * or http://www.opensolaris.org/os/licensing.
11*f0089e39SRichard Lowe  * See the License for the specific language governing permissions
12*f0089e39SRichard Lowe  * and limitations under the License.
13*f0089e39SRichard Lowe  *
14*f0089e39SRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
15*f0089e39SRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*f0089e39SRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
17*f0089e39SRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
18*f0089e39SRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
19*f0089e39SRichard Lowe  *
20*f0089e39SRichard Lowe  * CDDL HEADER END
21*f0089e39SRichard Lowe  */
22*f0089e39SRichard Lowe /*
23*f0089e39SRichard Lowe  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*f0089e39SRichard Lowe  * Use is subject to license terms.
25*f0089e39SRichard Lowe  */
26*f0089e39SRichard Lowe 
27*f0089e39SRichard Lowe /*
28*f0089e39SRichard Lowe  * Miscellaneous C routines for copying data around without
29*f0089e39SRichard Lowe  * descending into assembler.  Compilers are pretty good at
30*f0089e39SRichard Lowe  * scheduling instructions, and humans are pretty hopeless at
31*f0089e39SRichard Lowe  * writing correct assembler.
32*f0089e39SRichard Lowe  */
33*f0089e39SRichard Lowe 
34*f0089e39SRichard Lowe #include <sys/types.h>
35*f0089e39SRichard Lowe #include <sys/systm.h>
36*f0089e39SRichard Lowe #include <sys/errno.h>
37*f0089e39SRichard Lowe #include <sys/param.h>
38*f0089e39SRichard Lowe 
39*f0089e39SRichard Lowe /*
40*f0089e39SRichard Lowe  * copyinstr_noerr and copyoutstr_noerr can be implemented completely
41*f0089e39SRichard Lowe  * in C on machines with shared user and kernel context.
42*f0089e39SRichard Lowe  */
43*f0089e39SRichard Lowe static int
copystr_nofault(const char * src,char * dst,size_t maxlength,size_t * lencopied)44*f0089e39SRichard Lowe copystr_nofault(const char *src, char *dst, size_t maxlength,
45*f0089e39SRichard Lowe     size_t *lencopied)
46*f0089e39SRichard Lowe {
47*f0089e39SRichard Lowe 	int error = 0;
48*f0089e39SRichard Lowe 	size_t leftover;
49*f0089e39SRichard Lowe 
50*f0089e39SRichard Lowe 	if ((leftover = maxlength) == 0)
51*f0089e39SRichard Lowe 		error = ENAMETOOLONG;
52*f0089e39SRichard Lowe 	else
53*f0089e39SRichard Lowe 		do {
54*f0089e39SRichard Lowe 			leftover--;
55*f0089e39SRichard Lowe 			if ((*dst++ = *src++) == '\0')
56*f0089e39SRichard Lowe 				break;
57*f0089e39SRichard Lowe 			if (leftover == 0) {
58*f0089e39SRichard Lowe 				error = ENAMETOOLONG;
59*f0089e39SRichard Lowe 				break;
60*f0089e39SRichard Lowe 			}
61*f0089e39SRichard Lowe 		/*CONSTCOND*/
62*f0089e39SRichard Lowe 		} while (1);
63*f0089e39SRichard Lowe 
64*f0089e39SRichard Lowe 	if (lencopied)
65*f0089e39SRichard Lowe 		*lencopied = maxlength - leftover;
66*f0089e39SRichard Lowe 	return (error);
67*f0089e39SRichard Lowe }
68*f0089e39SRichard Lowe 
69*f0089e39SRichard Lowe 
70*f0089e39SRichard Lowe int
copyinstr_noerr(const char * uaddr,char * kaddr,size_t maxlength,size_t * lencopied)71*f0089e39SRichard Lowe copyinstr_noerr(const char *uaddr, char *kaddr, size_t maxlength,
72*f0089e39SRichard Lowe     size_t *lencopied)
73*f0089e39SRichard Lowe {
74*f0089e39SRichard Lowe 	char *ua = (char *)uaddr;
75*f0089e39SRichard Lowe 
76*f0089e39SRichard Lowe 	ASSERT((uintptr_t)kaddr > kernelbase);
77*f0089e39SRichard Lowe 
78*f0089e39SRichard Lowe 	if ((uintptr_t)ua > kernelbase) {
79*f0089e39SRichard Lowe 		/*
80*f0089e39SRichard Lowe 		 * force fault at kernelbase
81*f0089e39SRichard Lowe 		 */
82*f0089e39SRichard Lowe 		ua = (char *)kernelbase;
83*f0089e39SRichard Lowe 	}
84*f0089e39SRichard Lowe 	return (copystr_nofault(ua, kaddr, maxlength, lencopied));
85*f0089e39SRichard Lowe }
86*f0089e39SRichard Lowe 
87*f0089e39SRichard Lowe int
copyoutstr_noerr(const char * kaddr,char * uaddr,size_t maxlength,size_t * lencopied)88*f0089e39SRichard Lowe copyoutstr_noerr(const char *kaddr, char *uaddr, size_t maxlength,
89*f0089e39SRichard Lowe     size_t *lencopied)
90*f0089e39SRichard Lowe {
91*f0089e39SRichard Lowe 	char *ua = (char *)uaddr;
92*f0089e39SRichard Lowe 
93*f0089e39SRichard Lowe 	ASSERT((uintptr_t)kaddr > kernelbase);
94*f0089e39SRichard Lowe 
95*f0089e39SRichard Lowe 	if ((uintptr_t)ua > kernelbase) {
96*f0089e39SRichard Lowe 		/*
97*f0089e39SRichard Lowe 		 * force fault at kernelbase
98*f0089e39SRichard Lowe 		 */
99*f0089e39SRichard Lowe 		ua = (char *)kernelbase;
100*f0089e39SRichard Lowe 	}
101*f0089e39SRichard Lowe 	return (copystr_nofault(kaddr, ua, maxlength, lencopied));
102*f0089e39SRichard Lowe }
103