]>
Commit | Line | Data |
---|---|---|
51c22a5c CV |
1 | /* fhandler_mem.cc. See fhandler.h for a description of the fhandler classes. |
2 | ||
ec98d19a | 3 | Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. |
51c22a5c CV |
4 | |
5 | This file is part of Cygwin. | |
6 | ||
7 | This software is a copyrighted work licensed under the terms of the | |
8 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | #include "winsup.h" | |
51c22a5c | 12 | #include <unistd.h> |
51c22a5c | 13 | |
51c22a5c | 14 | #include "cygerrno.h" |
6b91b8d5 | 15 | #include "security.h" |
7ac61736 | 16 | #include "path.h" |
51c22a5c | 17 | #include "fhandler.h" |
8c8d0db4 | 18 | #include "ntdll.h" |
51c22a5c CV |
19 | |
20 | /**********************************************************************/ | |
21 | /* fhandler_dev_mem */ | |
22 | ||
7ac61736 CF |
23 | fhandler_dev_mem::fhandler_dev_mem () |
24 | : fhandler_base () | |
f4f898ac | 25 | { |
f8aae275 CV |
26 | } |
27 | ||
2f9ae2ed | 28 | fhandler_dev_mem::~fhandler_dev_mem () |
f8aae275 CV |
29 | { |
30 | } | |
31 | ||
32 | int | |
33 | fhandler_dev_mem::open (int flags, mode_t) | |
34 | { | |
ba946828 | 35 | if (!wincap.has_physical_mem_access ()) |
21fdffa5 | 36 | { |
f8aae275 | 37 | set_errno (ENOENT); |
8b827378 | 38 | debug_printf ("%s is accessible under NT4/W2K/XP only", dev ().name); |
f8aae275 | 39 | return 0; |
21fdffa5 CV |
40 | } |
41 | ||
7ac61736 | 42 | if (dev () == FH_MEM) /* /dev/mem */ |
f4f898ac | 43 | { |
42f1b6c5 CV |
44 | NTSTATUS ret; |
45 | SYSTEM_BASIC_INFORMATION sbi; | |
46 | if ((ret = NtQuerySystemInformation (SystemBasicInformation, (PVOID) &sbi, | |
1ff9f4b9 CF |
47 | sizeof sbi, NULL)) != STATUS_SUCCESS) |
48 | { | |
7460bfd3 CV |
49 | __seterrno_from_nt_status (ret); |
50 | debug_printf("NtQuerySystemInformation: ret %d, Dos(ret) %E", ret); | |
1ff9f4b9 CF |
51 | mem_size = 0; |
52 | } | |
42f1b6c5 | 53 | else |
1ff9f4b9 | 54 | mem_size = sbi.PhysicalPageSize * sbi.NumberOfPhysicalPages; |
44e93988 | 55 | debug_printf ("MemSize: %d MB", mem_size >> 20); |
4ea34a68 | 56 | } |
7ac61736 | 57 | else if (dev () == FH_KMEM) /* /dev/kmem - Not yet supported */ |
4ea34a68 CV |
58 | { |
59 | mem_size = 0; | |
44e93988 | 60 | debug_printf ("KMemSize: %d MB", mem_size >> 20); |
4ea34a68 | 61 | } |
f8aae275 | 62 | else if (dev () == FH_PORT) /* /dev/port == First 64K of /dev/mem */ |
4ea34a68 CV |
63 | { |
64 | mem_size = 65536; | |
65 | debug_printf ("PortSize: 64 KB"); | |
66 | } | |
67 | else | |
68 | { | |
42f1b6c5 CV |
69 | mem_size = 0; |
70 | debug_printf ("Illegal minor number!!!"); | |
f4f898ac | 71 | } |
51c22a5c | 72 | |
f4f898ac CV |
73 | /* Check for illegal flags. */ |
74 | if (flags & (O_APPEND | O_TRUNC | O_EXCL)) | |
75 | { | |
76 | set_errno (EINVAL); | |
77 | return 0; | |
78 | } | |
79 | ||
51c22a5c CV |
80 | UNICODE_STRING memstr; |
81 | RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory"); | |
82 | ||
83 | OBJECT_ATTRIBUTES attr; | |
c90e1cf1 CF |
84 | InitializeObjectAttributes (&attr, &memstr, |
85 | OBJ_CASE_INSENSITIVE | OBJ_INHERIT, | |
86 | NULL, NULL); | |
51c22a5c | 87 | |
f4f898ac | 88 | ACCESS_MASK section_access; |
ba31e832 | 89 | if ((flags & O_ACCMODE) == O_RDONLY) |
f4f898ac CV |
90 | { |
91 | set_access (GENERIC_READ); | |
92 | section_access = SECTION_MAP_READ; | |
93 | } | |
ba31e832 | 94 | else if ((flags & O_ACCMODE) == O_WRONLY) |
f4f898ac CV |
95 | { |
96 | set_access (GENERIC_WRITE); | |
97 | section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; | |
98 | } | |
51c22a5c | 99 | else |
f4f898ac CV |
100 | { |
101 | set_access (GENERIC_READ | GENERIC_WRITE); | |
102 | section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; | |
103 | } | |
51c22a5c CV |
104 | |
105 | HANDLE mem; | |
f4f898ac | 106 | NTSTATUS ret = NtOpenSection (&mem, section_access, &attr); |
f0227ea3 | 107 | if (!NT_SUCCESS (ret)) |
51c22a5c | 108 | { |
7460bfd3 | 109 | __seterrno_from_nt_status (ret); |
51c22a5c CV |
110 | set_io_handle (NULL); |
111 | return 0; | |
112 | } | |
113 | ||
114 | set_io_handle (mem); | |
f3ea62a8 | 115 | set_open_status (); |
51c22a5c CV |
116 | return 1; |
117 | } | |
118 | ||
119 | int | |
f4f898ac | 120 | fhandler_dev_mem::write (const void *ptr, size_t ulen) |
51c22a5c | 121 | { |
f4f898ac CV |
122 | if (!ulen || pos >= mem_size) |
123 | return 0; | |
124 | ||
125 | if (!(get_access () & GENERIC_WRITE)) | |
126 | { | |
127 | set_errno (EINVAL); | |
128 | return -1; | |
129 | } | |
130 | ||
131 | if (pos + ulen > mem_size) | |
132 | ulen = mem_size - pos; | |
133 | ||
134 | PHYSICAL_ADDRESS phys; | |
135 | NTSTATUS ret; | |
136 | void *viewmem = NULL; | |
f90e23f2 | 137 | DWORD len = ulen + getsystempagesize () - 1; |
f4f898ac CV |
138 | |
139 | phys.QuadPart = (ULONGLONG) pos; | |
140 | if ((ret = NtMapViewOfSection (get_handle (), | |
1ff9f4b9 CF |
141 | INVALID_HANDLE_VALUE, |
142 | &viewmem, | |
143 | 0L, | |
144 | len, | |
145 | &phys, | |
146 | &len, | |
147 | ViewShare, | |
148 | 0, | |
149 | PAGE_READONLY)) != STATUS_SUCCESS) | |
f4f898ac | 150 | { |
7460bfd3 | 151 | __seterrno_from_nt_status (ret); |
f4f898ac CV |
152 | return -1; |
153 | } | |
154 | ||
155 | memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, ulen); | |
156 | ||
f0227ea3 | 157 | if (!NT_SUCCESS (ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem))) |
f4f898ac | 158 | { |
7460bfd3 | 159 | __seterrno_from_nt_status (ret); |
f4f898ac CV |
160 | return -1; |
161 | } | |
162 | ||
163 | pos += ulen; | |
f4f898ac | 164 | return ulen; |
51c22a5c CV |
165 | } |
166 | ||
8bce0d72 CF |
167 | void __stdcall |
168 | fhandler_dev_mem::read (void *ptr, size_t& ulen) | |
51c22a5c | 169 | { |
f4f898ac | 170 | if (!ulen || pos >= mem_size) |
8bce0d72 CF |
171 | { |
172 | ulen = 0; | |
173 | return; | |
174 | } | |
51c22a5c | 175 | |
f4f898ac CV |
176 | if (!(get_access () & GENERIC_READ)) |
177 | { | |
178 | set_errno (EINVAL); | |
6cce721b | 179 | ulen = (size_t) -1; |
8bce0d72 | 180 | return; |
f4f898ac CV |
181 | } |
182 | ||
183 | if (pos + ulen > mem_size) | |
184 | ulen = mem_size - pos; | |
185 | ||
51c22a5c CV |
186 | PHYSICAL_ADDRESS phys; |
187 | NTSTATUS ret; | |
188 | void *viewmem = NULL; | |
f90e23f2 | 189 | DWORD len = ulen + getsystempagesize () - 1; |
51c22a5c CV |
190 | |
191 | phys.QuadPart = (ULONGLONG) pos; | |
192 | if ((ret = NtMapViewOfSection (get_handle (), | |
1ff9f4b9 CF |
193 | INVALID_HANDLE_VALUE, |
194 | &viewmem, | |
195 | 0L, | |
196 | len, | |
197 | &phys, | |
198 | &len, | |
199 | ViewShare, | |
200 | 0, | |
201 | PAGE_READONLY)) != STATUS_SUCCESS) | |
51c22a5c | 202 | { |
7460bfd3 | 203 | __seterrno_from_nt_status (ret); |
6cce721b | 204 | ulen = (size_t) -1; |
8bce0d72 | 205 | return; |
51c22a5c CV |
206 | } |
207 | ||
208 | memcpy (ptr, (char *) viewmem + (pos - phys.QuadPart), ulen); | |
209 | ||
f0227ea3 | 210 | if (!NT_SUCCESS (ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem))) |
51c22a5c | 211 | { |
7460bfd3 | 212 | __seterrno_from_nt_status (ret); |
6cce721b | 213 | ulen = (size_t) -1; |
8bce0d72 | 214 | return; |
51c22a5c CV |
215 | } |
216 | ||
217 | pos += ulen; | |
51c22a5c CV |
218 | } |
219 | ||
1727fba0 CV |
220 | _off64_t |
221 | fhandler_dev_mem::lseek (_off64_t offset, int whence) | |
51c22a5c CV |
222 | { |
223 | switch (whence) | |
224 | { | |
225 | case SEEK_SET: | |
226 | pos = offset; | |
227 | break; | |
75a57bf0 | 228 | |
51c22a5c CV |
229 | case SEEK_CUR: |
230 | pos += offset; | |
231 | break; | |
232 | ||
233 | case SEEK_END: | |
f4f898ac CV |
234 | pos = mem_size; |
235 | pos += offset; | |
51c22a5c | 236 | break; |
75a57bf0 | 237 | |
51c22a5c CV |
238 | default: |
239 | set_errno (EINVAL); | |
de4e0d30 | 240 | return ILLEGAL_SEEK; |
51c22a5c CV |
241 | } |
242 | ||
f4f898ac CV |
243 | if (pos > mem_size) |
244 | { | |
245 | set_errno (EINVAL); | |
de4e0d30 | 246 | return ILLEGAL_SEEK; |
f4f898ac CV |
247 | } |
248 | ||
51c22a5c CV |
249 | return pos; |
250 | } | |
251 | ||
252 | int | |
7ac61736 | 253 | fhandler_dev_mem::fstat (struct __stat64 *buf) |
51c22a5c | 254 | { |
7ac61736 | 255 | fhandler_base::fstat (buf); |
f90e23f2 | 256 | buf->st_blksize = getsystempagesize (); |
d6192578 CF |
257 | if (is_auto_device ()) |
258 | { | |
259 | buf->st_mode = S_IFCHR; | |
260 | if (wincap.has_physical_mem_access ()) | |
261 | buf->st_mode |= S_IRUSR | S_IWUSR | | |
262 | S_IRGRP | S_IWGRP | | |
263 | S_IROTH | S_IWOTH; | |
264 | } | |
51c22a5c CV |
265 | |
266 | return 0; | |
267 | } | |
268 | ||
269 | int | |
dcb091ca | 270 | fhandler_dev_mem::dup (fhandler_base *child) |
51c22a5c | 271 | { |
dcb091ca | 272 | int ret = fhandler_base::dup (child); |
f4f898ac CV |
273 | |
274 | if (! ret) | |
275 | { | |
276 | fhandler_dev_mem *fhc = (fhandler_dev_mem *) child; | |
277 | ||
278 | fhc->mem_size = mem_size; | |
279 | fhc->pos = pos; | |
280 | } | |
281 | return ret; | |
51c22a5c | 282 | } |