1/* 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} 164