symbian-qemu-0.9.1-12/qemu-symbian-svp/linux-user/uaccess.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* User memory access */
       
     2 #include <stdio.h>
       
     3 #include <string.h>
       
     4 
       
     5 #include "qemu.h"
       
     6 
       
     7 /* copy_from_user() and copy_to_user() are usually used to copy data
       
     8  * buffers between the target and host.  These internally perform
       
     9  * locking/unlocking of the memory.
       
    10  */
       
    11 abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
       
    12 {
       
    13     abi_long ret = 0;
       
    14     void *ghptr;
       
    15 
       
    16     if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
       
    17         memcpy(hptr, ghptr, len);
       
    18         unlock_user(ghptr, gaddr, 0);
       
    19     } else
       
    20         ret = -TARGET_EFAULT;
       
    21 
       
    22     return ret;
       
    23 }
       
    24 
       
    25 
       
    26 abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
       
    27 {
       
    28     abi_long ret = 0;
       
    29     void *ghptr;
       
    30 
       
    31     if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
       
    32         memcpy(ghptr, hptr, len);
       
    33 	unlock_user(ghptr, gaddr, len);
       
    34     } else
       
    35         ret = -TARGET_EFAULT;
       
    36 
       
    37     return ret;
       
    38 }
       
    39 
       
    40 /* XXX: use host strnlen if available ? */
       
    41 static int qemu_strnlen(const char *s, int max_len)
       
    42 {
       
    43     int i;
       
    44     for(i = 0; i < max_len; i++) {
       
    45         if (s[i] == '\0')
       
    46             break;
       
    47     }
       
    48     return i;
       
    49 }
       
    50 
       
    51 /* Return the length of a string in target memory or -TARGET_EFAULT if
       
    52    access error  */
       
    53 abi_long target_strlen(abi_ulong guest_addr1)
       
    54 {
       
    55     uint8_t *ptr;
       
    56     abi_ulong guest_addr;
       
    57     int max_len, len;
       
    58 
       
    59     guest_addr = guest_addr1;
       
    60     for(;;) {
       
    61         max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
       
    62         ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
       
    63         if (!ptr)
       
    64             return -TARGET_EFAULT;
       
    65         len = qemu_strnlen((const char *)ptr, max_len);
       
    66         unlock_user(ptr, guest_addr, 0);
       
    67         guest_addr += len;
       
    68         /* we don't allow wrapping or integer overflow */
       
    69         if (guest_addr == 0 || 
       
    70             (guest_addr - guest_addr1) > 0x7fffffff)
       
    71             return -TARGET_EFAULT;
       
    72         if (len != max_len)
       
    73             break;
       
    74     }
       
    75     return guest_addr - guest_addr1;
       
    76 }