blob: 7663e156ff4f8590b3a240ab5c8d2a79b4276513 [file] [log] [blame]
Ley Foon Tan5ccc6af52014-11-06 15:19:41 +08001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2009, Wind River Systems Inc
7 * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
8 */
9
10#include <linux/export.h>
11#include <linux/uaccess.h>
12
13asm(".global __copy_from_user\n"
14 " .type __copy_from_user, @function\n"
15 "__copy_from_user:\n"
16 " movi r2,7\n"
17 " mov r3,r4\n"
18 " bge r2,r6,1f\n"
19 " xor r2,r4,r5\n"
20 " andi r2,r2,3\n"
21 " movi r7,3\n"
22 " beq r2,zero,4f\n"
23 "1: addi r6,r6,-1\n"
24 " movi r2,-1\n"
25 " beq r6,r2,3f\n"
26 " mov r7,r2\n"
27 "2: ldbu r2,0(r5)\n"
28 " addi r6,r6,-1\n"
29 " addi r5,r5,1\n"
30 " stb r2,0(r3)\n"
31 " addi r3,r3,1\n"
32 " bne r6,r7,2b\n"
33 "3:\n"
34 " addi r2,r6,1\n"
35 " ret\n"
36 "13:mov r2,r6\n"
37 " ret\n"
38 "4: andi r2,r4,1\n"
39 " cmpeq r2,r2,zero\n"
40 " beq r2,zero,7f\n"
41 "5: andi r2,r3,2\n"
42 " beq r2,zero,6f\n"
43 "9: ldhu r2,0(r5)\n"
44 " addi r6,r6,-2\n"
45 " addi r5,r5,2\n"
46 " sth r2,0(r3)\n"
47 " addi r3,r3,2\n"
48 "6: bge r7,r6,1b\n"
49 "10:ldw r2,0(r5)\n"
50 " addi r6,r6,-4\n"
51 " addi r5,r5,4\n"
52 " stw r2,0(r3)\n"
53 " addi r3,r3,4\n"
54 " br 6b\n"
55 "7: ldbu r2,0(r5)\n"
56 " addi r6,r6,-1\n"
57 " addi r5,r5,1\n"
58 " addi r3,r4,1\n"
59 " stb r2,0(r4)\n"
60 " br 5b\n"
61 ".section __ex_table,\"a\"\n"
62 ".word 2b,3b\n"
63 ".word 9b,13b\n"
64 ".word 10b,13b\n"
65 ".word 7b,13b\n"
66 ".previous\n"
67 );
68EXPORT_SYMBOL(__copy_from_user);
69
70asm(
71 " .global __copy_to_user\n"
72 " .type __copy_to_user, @function\n"
73 "__copy_to_user:\n"
74 " movi r2,7\n"
75 " mov r3,r4\n"
76 " bge r2,r6,1f\n"
77 " xor r2,r4,r5\n"
78 " andi r2,r2,3\n"
79 " movi r7,3\n"
80 " beq r2,zero,4f\n"
81 /* Bail if we try to copy zero bytes */
82 "1: addi r6,r6,-1\n"
83 " movi r2,-1\n"
84 " beq r6,r2,3f\n"
85 /* Copy byte by byte for small copies and if src^dst != 0 */
86 " mov r7,r2\n"
87 "2: ldbu r2,0(r5)\n"
88 " addi r5,r5,1\n"
89 "9: stb r2,0(r3)\n"
90 " addi r6,r6,-1\n"
91 " addi r3,r3,1\n"
92 " bne r6,r7,2b\n"
93 "3: addi r2,r6,1\n"
94 " ret\n"
95 "13:mov r2,r6\n"
96 " ret\n"
97 /* If 'to' is an odd address byte copy */
98 "4: andi r2,r4,1\n"
99 " cmpeq r2,r2,zero\n"
100 " beq r2,zero,7f\n"
101 /* If 'to' is not divideable by four copy halfwords */
102 "5: andi r2,r3,2\n"
103 " beq r2,zero,6f\n"
104 " ldhu r2,0(r5)\n"
105 " addi r5,r5,2\n"
106 "10:sth r2,0(r3)\n"
107 " addi r6,r6,-2\n"
108 " addi r3,r3,2\n"
109 /* Copy words */
110 "6: bge r7,r6,1b\n"
111 " ldw r2,0(r5)\n"
112 " addi r5,r5,4\n"
113 "11:stw r2,0(r3)\n"
114 " addi r6,r6,-4\n"
115 " addi r3,r3,4\n"
116 " br 6b\n"
117 /* Copy remaining bytes */
118 "7: ldbu r2,0(r5)\n"
119 " addi r5,r5,1\n"
120 " addi r3,r4,1\n"
121 "12: stb r2,0(r4)\n"
122 " addi r6,r6,-1\n"
123 " br 5b\n"
124 ".section __ex_table,\"a\"\n"
125 ".word 9b,3b\n"
126 ".word 10b,13b\n"
127 ".word 11b,13b\n"
128 ".word 12b,13b\n"
129 ".previous\n");
130EXPORT_SYMBOL(__copy_to_user);
131
132long strncpy_from_user(char *__to, const char __user *__from, long __len)
133{
134 int l = strnlen_user(__from, __len);
135 int is_zt = 1;
136
137 if (l > __len) {
138 is_zt = 0;
139 l = __len;
140 }
141
142 if (l == 0 || copy_from_user(__to, __from, l))
143 return -EFAULT;
144
145 if (is_zt)
146 l--;
147 return l;
148}
149
150long strnlen_user(const char __user *s, long n)
151{
152 long i;
153
154 for (i = 0; i < n; i++) {
155 char c;
156
157 if (get_user(c, s + i) == -EFAULT)
158 return 0;
159 if (c == 0)
160 return i + 1;
161 }
162 return n + 1;
163}