1 /* fhandler_mem.cc. See fhandler.h for a description of the fhandler classes.
3 Copyright 1999, 2000 Cygnus Solutions.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #include <sys/termios.h>
26 * The following both data structures aren't defined anywhere in the Microsoft
27 * header files. Taken from the book "Windows NT/2000 Native API Reference"
30 typedef enum _SYSTEM_INFORMATION_CLASS {
31 SystemBasicInformation = 0
32 /* Dropped each other since not used here. */
33 } SYSTEM_INFORMATION_CLASS;
35 typedef struct _SYSTEM_BASIC_INFORMATION {
37 ULONG MaximumIncrement;
38 ULONG PhysicalPageSize;
39 ULONG NumberOfPhysicalPages;
40 ULONG LowestPhysicalPage;
41 ULONG HighestPhysicalPage;
42 ULONG AllocationGranularity;
43 ULONG LowestUserAddress;
44 ULONG HighestUserAddress;
45 ULONG ActiveProcessors;
46 ULONG NumberProcessors;
47 } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
50 NTSTATUS NTAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,ULONG,
51 PLARGE_INTEGER,PULONG,SECTION_INHERIT,
53 NTSTATUS NTAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS,
55 NTSTATUS NTAPI NtOpenSection(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);
56 NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE,PVOID);
57 VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING,PCWSTR);
58 ULONG NTAPI RtlNtStatusToDosError(NTSTATUS);
61 /**********************************************************************/
62 /* fhandler_dev_mem */
64 fhandler_dev_mem::fhandler_dev_mem (const char *name, int nunit)
65 : fhandler_base (FH_MEM, name),
68 if (unit == 1) /* /dev/mem */
71 SYSTEM_BASIC_INFORMATION sbi;
72 if ((ret = NtQuerySystemInformation (SystemBasicInformation, (PVOID) &sbi,
73 sizeof sbi, NULL)) != STATUS_SUCCESS)
75 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
76 debug_printf("NtQuerySystemInformation: ret = %d, Dos(ret) = %d",
77 ret, RtlNtStatusToDosError (ret));
81 mem_size = sbi.PhysicalPageSize * sbi.NumberOfPhysicalPages;
82 debug_printf ("MemSize: %d MB", mem_size >>= 20);
84 else if (unit == 2) /* /dev/kmem - Not yet supported */
87 debug_printf ("KMemSize: %d MB", mem_size >>= 20);
89 else if (unit == 4) /* /dev/port == First 64K of /dev/mem */
92 debug_printf ("PortSize: 64 KB");
97 debug_printf ("Illegal minor number!!!");
101 fhandler_dev_mem::~fhandler_dev_mem (void)
106 fhandler_dev_mem::open (const char *, int flags, mode_t)
108 if (os_being_run != winNT)
111 debug_printf ("%s is accessible under NT/W2K only",
112 unit == 1 ? "/dev/mem" :
113 unit == 2 ? "/dev/kmem" :
118 /* Check for illegal flags. */
119 if (flags & (O_APPEND | O_TRUNC | O_EXCL))
125 UNICODE_STRING memstr;
126 RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory");
128 OBJECT_ATTRIBUTES attr;
129 InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL);
131 ACCESS_MASK section_access;
132 if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
134 set_access (GENERIC_READ);
135 section_access = SECTION_MAP_READ;
137 else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
139 set_access (GENERIC_WRITE);
140 section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
144 set_access (GENERIC_READ | GENERIC_WRITE);
145 section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
149 NTSTATUS ret = NtOpenSection (&mem, section_access, &attr);
150 if (!NT_SUCCESS(ret))
152 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
153 set_io_handle (NULL);
162 fhandler_dev_mem::write (const void *ptr, size_t ulen)
164 if (!ulen || pos >= mem_size)
167 if (!(get_access () & GENERIC_WRITE))
173 if (pos + ulen > mem_size)
174 ulen = mem_size - pos;
176 PHYSICAL_ADDRESS phys;
178 void *viewmem = NULL;
179 DWORD len = ulen + getpagesize () - 1;
181 phys.QuadPart = (ULONGLONG) pos;
182 if ((ret = NtMapViewOfSection (get_handle (),
183 INVALID_HANDLE_VALUE,
191 PAGE_READONLY)) != STATUS_SUCCESS)
193 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
197 memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, ulen);
199 if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
201 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
210 fhandler_dev_mem::read (void *ptr, size_t ulen)
212 if (!ulen || pos >= mem_size)
215 if (!(get_access () & GENERIC_READ))
221 if (pos + ulen > mem_size)
222 ulen = mem_size - pos;
224 PHYSICAL_ADDRESS phys;
226 void *viewmem = NULL;
227 DWORD len = ulen + getpagesize () - 1;
229 phys.QuadPart = (ULONGLONG) pos;
230 if ((ret = NtMapViewOfSection (get_handle (),
231 INVALID_HANDLE_VALUE,
239 PAGE_READONLY)) != STATUS_SUCCESS)
241 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
245 memcpy (ptr, (char *) viewmem + (pos - phys.QuadPart), ulen);
247 if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
249 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
258 fhandler_dev_mem::close (void)
260 return fhandler_base::close ();
264 fhandler_dev_mem::lseek (off_t offset, int whence)
296 fhandler_dev_mem::mmap (caddr_t *addr, size_t len, DWORD access,
297 int flags, off_t off)
299 if ((DWORD) off >= mem_size
300 || (DWORD) len >= mem_size
301 || (DWORD) off + len >= mem_size)
304 syscall_printf ("-1 = mmap(): illegal parameter, set EINVAL");
305 return INVALID_HANDLE_VALUE;
308 UNICODE_STRING memstr;
309 RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory");
311 OBJECT_ATTRIBUTES attr;
312 InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL);
314 ACCESS_MASK section_access;
317 if (access & FILE_MAP_COPY)
319 section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
320 protect = PAGE_WRITECOPY;
322 else if (access & FILE_MAP_WRITE)
324 section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
325 protect = PAGE_READWRITE;
329 section_access = SECTION_MAP_READ;
330 protect = PAGE_READONLY;
334 NTSTATUS ret = NtOpenSection (&h, section_access, &attr);
335 if (!NT_SUCCESS(ret))
337 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
338 syscall_printf ("-1 = mmap(): NtOpenSection failed with %E");
339 return INVALID_HANDLE_VALUE;
342 PHYSICAL_ADDRESS phys;
346 phys.QuadPart = (ULONGLONG) off;
348 if ((ret = NtMapViewOfSection (h,
349 INVALID_HANDLE_VALUE,
357 protect)) != STATUS_SUCCESS)
359 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
360 syscall_printf ("-1 = mmap(): NtMapViewOfSection failed with %E");
361 return INVALID_HANDLE_VALUE;
363 if ((flags & MAP_FIXED) && base != addr)
366 syscall_printf ("-1 = mmap(): address shift with MAP_FIXED given");
367 NtUnmapViewOfSection (INVALID_HANDLE_VALUE, base);
368 return INVALID_HANDLE_VALUE;
371 *addr = (caddr_t) base;
376 fhandler_dev_mem::munmap (HANDLE h, caddr_t addr, size_t len)
379 if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, addr)))
381 __seterrno_from_win_error (RtlNtStatusToDosError (ret));
389 fhandler_dev_mem::msync (HANDLE h, caddr_t addr, size_t len, int flags)
395 fhandler_dev_mem::fstat (struct stat *buf)
403 memset (buf, 0, sizeof *buf);
404 buf->st_mode = S_IFCHR;
405 if (os_being_run != winNT)
406 buf->st_mode |= S_IRUSR | S_IWUSR |
410 buf->st_blksize = getpagesize ();
411 buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff);
417 fhandler_dev_mem::dup (fhandler_base *child)
419 int ret = fhandler_base::dup (child);
423 fhandler_dev_mem *fhc = (fhandler_dev_mem *) child;
425 fhc->mem_size = mem_size;
432 fhandler_dev_mem::dump ()
434 paranoid_printf("here, fhandler_dev_mem");
439 LoadDLLinitfunc (ntdll)
442 static NO_COPY LONG here = -1L;
444 while (InterlockedIncrement (&here))
446 InterlockedDecrement (&here);
447 small_printf ("Multiple tries to read ntdll.dll\n");
453 else if ((h = LoadLibrary ("ntdll.dll")) != NULL)
455 else if (!ntdll_handle)
456 api_fatal ("could not load ntdll.dll, %E");
458 InterlockedDecrement (&here);
462 static void dummy_autoload (void) __attribute__ ((unused));
464 dummy_autoload (void)
467 LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
468 LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1)
469 LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
470 LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
471 LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
472 LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)