OSDN Git Service

* fhandler_mem.cc: Eliminate unused include statements.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / fhandler_mem.cc
1 /* fhandler_mem.cc.  See fhandler.h for a description of the fhandler classes.
2
3    Copyright 1999, 2000 Cygnus Solutions.
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"
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <unistd.h>
15 #include <sys/mman.h>
16 #include <ntdef.h>
17
18 #include "autoload.h"
19 #include "cygerrno.h"
20 #include "fhandler.h"
21
22 /*
23  * The following both data structures aren't defined anywhere in the Microsoft
24  * header files. Taken from the book "Windows NT/2000 Native API Reference"
25  * by Gary Nebbett.
26  */
27 typedef enum _SYSTEM_INFORMATION_CLASS {
28   SystemBasicInformation = 0
29   /* Dropped each other since not used here. */
30 } SYSTEM_INFORMATION_CLASS;
31
32 typedef struct _SYSTEM_BASIC_INFORMATION {
33   ULONG Unknown;
34   ULONG MaximumIncrement;
35   ULONG PhysicalPageSize;
36   ULONG NumberOfPhysicalPages;
37   ULONG LowestPhysicalPage;
38   ULONG HighestPhysicalPage;
39   ULONG AllocationGranularity;
40   ULONG LowestUserAddress;
41   ULONG HighestUserAddress;
42   ULONG ActiveProcessors;
43   ULONG NumberProcessors;
44 } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
45
46 extern "C" {
47 NTSTATUS NTAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,ULONG,
48                                   PLARGE_INTEGER,PULONG,SECTION_INHERIT,
49                                   ULONG,ULONG);
50 NTSTATUS NTAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS,
51                                         PVOID,ULONG,PULONG);
52 NTSTATUS NTAPI NtOpenSection(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);
53 NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE,PVOID);
54 VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING,PCWSTR);
55 ULONG NTAPI RtlNtStatusToDosError(NTSTATUS);
56 }
57
58 /**********************************************************************/
59 /* fhandler_dev_mem */
60
61 fhandler_dev_mem::fhandler_dev_mem (const char *name, int nunit)
62 : fhandler_base (FH_MEM, name),
63   unit (nunit)
64 {
65   /* Reading physical memory only supported on NT/W2K. */
66   if (os_being_run != winNT)
67     {
68       mem_size = 0;
69       return;
70     }
71
72   if (unit == 1) /* /dev/mem */
73     {
74       NTSTATUS ret;
75       SYSTEM_BASIC_INFORMATION sbi;
76       if ((ret = NtQuerySystemInformation (SystemBasicInformation, (PVOID) &sbi,
77                                            sizeof sbi, NULL)) != STATUS_SUCCESS)
78         {
79           __seterrno_from_win_error (RtlNtStatusToDosError (ret));
80           debug_printf("NtQuerySystemInformation: ret = %d, Dos(ret) = %d",
81                        ret, RtlNtStatusToDosError (ret));
82           mem_size = 0;
83         }
84       else
85         mem_size = sbi.PhysicalPageSize * sbi.NumberOfPhysicalPages;
86       debug_printf ("MemSize: %d MB", mem_size >>= 20);
87     }
88   else if (unit == 2) /* /dev/kmem - Not yet supported */
89     {
90       mem_size = 0;
91       debug_printf ("KMemSize: %d MB", mem_size >>= 20);
92     }
93   else if (unit == 4) /* /dev/port == First 64K of /dev/mem */
94     {
95       mem_size = 65536;
96       debug_printf ("PortSize: 64 KB");
97     }
98   else
99     {
100       mem_size = 0;
101       debug_printf ("Illegal minor number!!!");
102     }
103 }
104
105 fhandler_dev_mem::~fhandler_dev_mem (void)
106 {
107 }
108
109 int
110 fhandler_dev_mem::open (const char *, int flags, mode_t)
111 {
112   if (os_being_run != winNT)
113     {
114       set_errno (ENOENT);
115       debug_printf ("%s is accessible under NT/W2K only",
116                     unit == 1 ? "/dev/mem" :
117                     unit == 2 ? "/dev/kmem" :
118                                 "/dev/port" );
119       return 0;
120     }
121
122   /* Check for illegal flags. */
123   if (flags & (O_APPEND | O_TRUNC | O_EXCL))
124     {
125       set_errno (EINVAL);
126       return 0;
127     }
128
129   UNICODE_STRING memstr;
130   RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory");
131
132   OBJECT_ATTRIBUTES attr;
133   InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL);
134
135   ACCESS_MASK section_access;
136   if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
137     {
138       set_access (GENERIC_READ);
139       section_access = SECTION_MAP_READ;
140     }
141   else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
142     {
143       set_access (GENERIC_WRITE);
144       section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
145     }
146   else
147     {
148       set_access (GENERIC_READ | GENERIC_WRITE);
149       section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
150     }
151
152   HANDLE mem;
153   NTSTATUS ret = NtOpenSection (&mem, section_access, &attr);
154   if (!NT_SUCCESS(ret))
155     {
156       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
157       set_io_handle (NULL);
158       return 0;
159     }
160
161   set_io_handle (mem);
162   return 1;
163 }
164
165 int
166 fhandler_dev_mem::write (const void *ptr, size_t ulen)
167 {
168   if (!ulen || pos >= mem_size)
169     return 0;
170
171   if (!(get_access () & GENERIC_WRITE))
172     {
173       set_errno (EINVAL);
174       return -1;
175     }
176
177   if (pos + ulen > mem_size)
178     ulen = mem_size - pos;
179
180   PHYSICAL_ADDRESS phys;
181   NTSTATUS ret;
182   void *viewmem = NULL;
183   DWORD len = ulen + getpagesize () - 1;
184
185   phys.QuadPart = (ULONGLONG) pos;
186   if ((ret = NtMapViewOfSection (get_handle (),
187                                  INVALID_HANDLE_VALUE,
188                                  &viewmem,
189                                  0L,
190                                  len,
191                                  &phys,
192                                  &len,
193                                  ViewShare,
194                                  0,
195                                  PAGE_READONLY)) != STATUS_SUCCESS)
196     {
197       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
198       return -1;
199     }
200
201   memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, ulen);
202
203   if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
204     {
205       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
206       return -1;
207     }
208
209   pos += ulen;
210   return ulen;
211 }
212
213 int
214 fhandler_dev_mem::read (void *ptr, size_t ulen)
215 {
216   if (!ulen || pos >= mem_size)
217     return 0;
218
219   if (!(get_access () & GENERIC_READ))
220     {
221       set_errno (EINVAL);
222       return -1;
223     }
224
225   if (pos + ulen > mem_size)
226     ulen = mem_size - pos;
227
228   PHYSICAL_ADDRESS phys;
229   NTSTATUS ret;
230   void *viewmem = NULL;
231   DWORD len = ulen + getpagesize () - 1;
232
233   phys.QuadPart = (ULONGLONG) pos;
234   if ((ret = NtMapViewOfSection (get_handle (),
235                                  INVALID_HANDLE_VALUE,
236                                  &viewmem,
237                                  0L,
238                                  len,
239                                  &phys,
240                                  &len,
241                                  ViewShare,
242                                  0,
243                                  PAGE_READONLY)) != STATUS_SUCCESS)
244     {
245       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
246       return -1;
247     }
248
249   memcpy (ptr, (char *) viewmem + (pos - phys.QuadPart), ulen);
250
251   if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
252     {
253       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
254       return -1;
255     }
256
257   pos += ulen;
258   return ulen;
259 }
260
261 int
262 fhandler_dev_mem::close (void)
263 {
264   return fhandler_base::close ();
265 }
266
267 off_t
268 fhandler_dev_mem::lseek (off_t offset, int whence)
269 {
270   switch (whence)
271     {
272     case SEEK_SET:
273       pos = offset;
274       break;
275     
276     case SEEK_CUR:
277       pos += offset;
278       break;
279
280     case SEEK_END:
281       pos = mem_size;
282       pos += offset;
283       break;
284     
285     default:
286       set_errno (EINVAL);
287       return (off_t) -1;
288     }
289
290   if (pos > mem_size)
291     {
292       set_errno (EINVAL);
293       return (off_t) -1;
294     }
295
296   return pos;
297 }
298
299 HANDLE
300 fhandler_dev_mem::mmap (caddr_t *addr, size_t len, DWORD access,
301                         int flags, off_t off)
302 {
303   if ((DWORD) off >= mem_size
304       || (DWORD) len >= mem_size
305       || (DWORD) off + len >= mem_size)
306     {
307       set_errno (EINVAL);
308       syscall_printf ("-1 = mmap(): illegal parameter, set EINVAL");
309       return INVALID_HANDLE_VALUE;
310     }
311
312   UNICODE_STRING memstr;
313   RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory");
314
315   OBJECT_ATTRIBUTES attr;
316   InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL);
317
318   ACCESS_MASK section_access;
319   ULONG protect;
320
321   if (access & FILE_MAP_COPY)
322     {
323       section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
324       protect = PAGE_WRITECOPY;
325     }
326   else if (access & FILE_MAP_WRITE)
327     {
328       section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
329       protect = PAGE_READWRITE;
330     }
331   else
332     {
333       section_access = SECTION_MAP_READ;
334       protect = PAGE_READONLY;
335     }
336
337   HANDLE h;
338   NTSTATUS ret = NtOpenSection (&h, section_access, &attr);
339   if (!NT_SUCCESS(ret))
340     {
341       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
342       syscall_printf ("-1 = mmap(): NtOpenSection failed with %E");
343       return INVALID_HANDLE_VALUE;
344     }
345
346   PHYSICAL_ADDRESS phys;
347   void *base = *addr;
348   DWORD dlen = len;
349
350   phys.QuadPart = (ULONGLONG) off;
351
352   if ((ret = NtMapViewOfSection (h,
353                                  INVALID_HANDLE_VALUE,
354                                  &base,
355                                  0L,
356                                  dlen,
357                                  &phys,
358                                  &dlen,
359                                  ViewShare /*??*/,
360                                  0,
361                                  protect)) != STATUS_SUCCESS)
362     {
363       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
364       syscall_printf ("-1 = mmap(): NtMapViewOfSection failed with %E");
365       return INVALID_HANDLE_VALUE;
366     }
367   if ((flags & MAP_FIXED) && base != addr)
368     {
369       set_errno (EINVAL);
370       syscall_printf ("-1 = mmap(): address shift with MAP_FIXED given");
371       NtUnmapViewOfSection (INVALID_HANDLE_VALUE, base);
372       return INVALID_HANDLE_VALUE;
373     }
374
375   *addr = (caddr_t) base;
376   return h;
377 }
378
379 int
380 fhandler_dev_mem::munmap (HANDLE h, caddr_t addr, size_t len)
381 {
382   NTSTATUS ret;
383   if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, addr)))
384     {
385       __seterrno_from_win_error (RtlNtStatusToDosError (ret));
386       return -1;
387     }
388   CloseHandle (h);
389   return 0;
390 }
391
392 int
393 fhandler_dev_mem::msync (HANDLE h, caddr_t addr, size_t len, int flags)
394 {
395   return 0;
396 }
397
398 int
399 fhandler_dev_mem::fstat (struct stat *buf)
400 {
401   if (!buf)
402     {
403       set_errno (EINVAL);
404       return -1;
405     }
406
407   memset (buf, 0, sizeof *buf);
408   buf->st_mode = S_IFCHR;
409   if (os_being_run != winNT)
410     buf->st_mode |= S_IRUSR | S_IWUSR |
411                     S_IRGRP | S_IWGRP |
412                     S_IROTH | S_IWOTH;
413   buf->st_nlink = 1;
414   buf->st_blksize = getpagesize ();
415   buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff);
416
417   return 0;
418 }
419
420 int
421 fhandler_dev_mem::dup (fhandler_base *child)
422 {
423   int ret = fhandler_base::dup (child);
424
425   if (! ret)
426     {
427       fhandler_dev_mem *fhc = (fhandler_dev_mem *) child;
428
429       fhc->mem_size = mem_size;
430       fhc->pos = pos;
431     }
432   return ret;
433 }
434
435 void
436 fhandler_dev_mem::dump ()
437 {
438   paranoid_printf("here, fhandler_dev_mem");
439 }
440
441 extern "C" {
442
443 LoadDLLinitfunc (ntdll)
444 {
445   HANDLE h;
446   static NO_COPY LONG here = -1L;
447
448   while (InterlockedIncrement (&here))
449     {
450       InterlockedDecrement (&here);
451 small_printf ("Multiple tries to read ntdll.dll\n");
452       Sleep (0);
453     }
454
455   if (ntdll_handle)
456     /* nothing to do */;
457   else if ((h = LoadLibrary ("ntdll.dll")) != NULL)
458     ntdll_handle = h;
459   else if (!ntdll_handle)
460     api_fatal ("could not load ntdll.dll, %E");
461
462   InterlockedDecrement (&here);
463   return 0;
464 }
465
466 static void dummy_autoload (void) __attribute__ ((unused));
467 static void
468 dummy_autoload (void)
469 {
470 LoadDLLinit (ntdll)
471 LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
472 LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1)
473 LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
474 LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
475 LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
476 LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
477 }
478 }