]>
Commit | Line | Data |
---|---|---|
84778508 | 1 | /* User memory access */ |
2231197c | 2 | #include "qemu/osdep.h" |
84778508 BS |
3 | |
4 | #include "qemu.h" | |
5 | ||
6 | /* copy_from_user() and copy_to_user() are usually used to copy data | |
7 | * buffers between the target and host. These internally perform | |
8 | * locking/unlocking of the memory. | |
9 | */ | |
10 | abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len) | |
11 | { | |
12 | abi_long ret = 0; | |
13 | void *ghptr; | |
14 | ||
15 | if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) { | |
16 | memcpy(hptr, ghptr, len); | |
17 | unlock_user(ghptr, gaddr, 0); | |
18 | } else | |
19 | ret = -TARGET_EFAULT; | |
20 | ||
21 | return ret; | |
22 | } | |
23 | ||
24 | ||
25 | abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len) | |
26 | { | |
27 | abi_long ret = 0; | |
28 | void *ghptr; | |
29 | ||
30 | if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) { | |
31 | memcpy(ghptr, hptr, len); | |
32 | unlock_user(ghptr, gaddr, len); | |
33 | } else | |
34 | ret = -TARGET_EFAULT; | |
35 | ||
36 | return ret; | |
37 | } | |
38 | ||
84778508 BS |
39 | /* Return the length of a string in target memory or -TARGET_EFAULT if |
40 | access error */ | |
41 | abi_long target_strlen(abi_ulong guest_addr1) | |
42 | { | |
43 | uint8_t *ptr; | |
44 | abi_ulong guest_addr; | |
45 | int max_len, len; | |
46 | ||
47 | guest_addr = guest_addr1; | |
48 | for(;;) { | |
49 | max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK); | |
50 | ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1); | |
51 | if (!ptr) | |
52 | return -TARGET_EFAULT; | |
fff2a02f | 53 | len = qemu_strnlen((char *)ptr, max_len); |
84778508 BS |
54 | unlock_user(ptr, guest_addr, 0); |
55 | guest_addr += len; | |
56 | /* we don't allow wrapping or integer overflow */ | |
57 | if (guest_addr == 0 || | |
58 | (guest_addr - guest_addr1) > 0x7fffffff) | |
59 | return -TARGET_EFAULT; | |
60 | if (len != max_len) | |
61 | break; | |
62 | } | |
63 | return guest_addr - guest_addr1; | |
64 | } |