From a8126a9ea86b3e94af9edd7d3dbc1e0a950ea585 Mon Sep 17 00:00:00 2001 From: corinna Date: Sat, 7 Oct 2000 17:35:36 +0000 Subject: [PATCH] * fhandler.h (fhandler_dev_mem): Add methods mmap, munmap and msync. Add `unit' member. * fhandler_mem.cc (fhandler_dev_mem): Initialize `unit' as well. (init): Care for differences between /dev/mem, /dev/kmem (not implemented yet) and /dev/port. (open): Change debug message to reflect the device. (mmap): New function. (munmap): Ditto. (msync): Ditto. (fstat): Use unit when setting st_dev in stat structure. * mmap.cc (mmap): Handle MAP_ANONYMOUS flag. Change error handling slightly. * path.cc (get_device_number): Handle /dev/port. --- winsup/cygwin/ChangeLog | 16 +++++ winsup/cygwin/fhandler.h | 16 +++-- winsup/cygwin/fhandler_mem.cc | 159 ++++++++++++++++++++++++++++++++++++------ winsup/cygwin/mmap.cc | 14 +++- winsup/cygwin/path.cc | 10 ++- 5 files changed, 185 insertions(+), 30 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ef54862354..f00bf5bd37 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +Sat Oct 7 19:25:00 2000 Corinna Vinschen + + * fhandler.h (fhandler_dev_mem): Add methods mmap, munmap and msync. + Add `unit' member. + * fhandler_mem.cc (fhandler_dev_mem): Initialize `unit' as well. + (init): Care for differences between /dev/mem, /dev/kmem (not + implemented yet) and /dev/port. + (open): Change debug message to reflect the device. + (mmap): New function. + (munmap): Ditto. + (msync): Ditto. + (fstat): Use unit when setting st_dev in stat structure. + * mmap.cc (mmap): Handle MAP_ANONYMOUS flag. + Change error handling slightly. + * path.cc (get_device_number): Handle /dev/port. + Fri Oct 6 23:21:29 2000 Christopher Faylor * syscalls.cc (_read): Behave properly when passed previous version of diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 16b0e73321..3f8a1c1e03 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -467,10 +467,9 @@ public: BOOL is_device () { return FALSE; } int fstat (struct stat *buf); - virtual HANDLE mmap (caddr_t *addr, size_t len, DWORD access, - int flags, off_t off); - virtual int munmap (HANDLE h, caddr_t addr, size_t len); - virtual int msync (HANDLE h, caddr_t addr, size_t len, int flags); + HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off); + int munmap (HANDLE h, caddr_t addr, size_t len); + int msync (HANDLE h, caddr_t addr, size_t len, int flags); }; class fhandler_serial: public fhandler_base @@ -777,8 +776,9 @@ public: class fhandler_dev_mem: public fhandler_base { protected: - unsigned long mem_size; - unsigned long pos; + int unit; + DWORD mem_size; + DWORD pos; bool init_phase; void init (void); @@ -795,6 +795,10 @@ public: int fstat (struct stat *buf); int dup (fhandler_base *child); + HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off); + int munmap (HANDLE h, caddr_t addr, size_t len); + int msync (HANDLE h, caddr_t addr, size_t len, int flags); + void dump (); }; diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc index 10213e6562..ae86f3f550 100644 --- a/winsup/cygwin/fhandler_mem.cc +++ b/winsup/cygwin/fhandler_mem.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "autoload.h" @@ -34,9 +35,10 @@ ULONG NTAPI RtlNtStatusToDosError(NTSTATUS); /**********************************************************************/ /* fhandler_dev_mem */ -fhandler_dev_mem::fhandler_dev_mem (const char *name, int) +fhandler_dev_mem::fhandler_dev_mem (const char *name, int nunit) : fhandler_base (FH_MEM, name), - init_phase(false) + unit (nunit), + init_phase (false) { } @@ -47,24 +49,41 @@ fhandler_dev_mem::~fhandler_dev_mem (void) void fhandler_dev_mem::init () { - long page_size = getpagesize (); - char buf[1]; - - init_phase = true; - mem_size = pos = 1 << 30; - for (off_t afct = 1 << 29; afct >= page_size; afct >>= 1) + if (unit == 1) /* /dev/mem */ { - if (read (buf, 1) > 0) - pos += afct; - else + long page_size = getpagesize (); + char buf[1]; + + init_phase = true; + mem_size = pos = 1 << 30; + for (off_t afct = 1 << 29; afct >= page_size; afct >>= 1) { - if (pos < mem_size) - mem_size = pos; - pos -= afct; + if (read (buf, 1) > 0) + pos += afct; + else + { + if (pos < mem_size) + mem_size = pos; + pos -= afct; + } } + pos = 0; + debug_printf ("MemSize: %d MB", mem_size >>= 20); + } + else if (unit == 2) /* /dev/kmem - Not yet supported */ + { + mem_size = 0; + debug_printf ("KMemSize: %d MB", mem_size >>= 20); + } + else if (unit == 4) /* /dev/port == First 64K of /dev/mem */ + { + mem_size = 65536; + debug_printf ("PortSize: 64 KB"); + } + else + { + debug_printf ("Illegal unit!!!"); } - pos = 0; - debug_printf ("MemSize: %d MB", mem_size >>= 20); init_phase = false; } @@ -74,7 +93,10 @@ fhandler_dev_mem::open (const char *, int flags, mode_t) if (os_being_run != winNT) { set_errno (ENOENT); - debug_printf ("/dev/mem is accessible under NT/W2K only"); + debug_printf ("%s is accessible under NT/W2K only", + unit == 1 ? "/dev/mem" : + unit == 2 ? "/dev/kmem" : + "/dev/port" ); return 0; } @@ -167,7 +189,6 @@ fhandler_dev_mem::write (const void *ptr, size_t ulen) } pos += ulen; - return ulen; } @@ -217,7 +238,6 @@ fhandler_dev_mem::read (void *ptr, size_t ulen) } pos += ulen; - return ulen; } @@ -259,6 +279,105 @@ fhandler_dev_mem::lseek (off_t offset, int whence) return pos; } +HANDLE +fhandler_dev_mem::mmap (caddr_t *addr, size_t len, DWORD access, + int flags, off_t off) +{ + if ((DWORD) off >= mem_size + || (DWORD) len >= mem_size + || (DWORD) off + len >= mem_size) + { + set_errno (EINVAL); + syscall_printf ("-1 = mmap(): illegal parameter, set EINVAL"); + return INVALID_HANDLE_VALUE; + } + + UNICODE_STRING memstr; + RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory"); + + OBJECT_ATTRIBUTES attr; + InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL); + + ACCESS_MASK section_access; + ULONG protect; + + if (access & FILE_MAP_COPY) + { + section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; + protect = PAGE_WRITECOPY; + } + else if (access & FILE_MAP_WRITE) + { + section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; + protect = PAGE_READWRITE; + } + else + { + section_access = SECTION_MAP_READ; + protect = PAGE_READONLY; + } + + HANDLE h; + NTSTATUS ret = NtOpenSection (&h, section_access, &attr); + if (!NT_SUCCESS(ret)) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + syscall_printf ("-1 = mmap(): NtOpenSection failed with %E"); + return INVALID_HANDLE_VALUE; + } + + PHYSICAL_ADDRESS phys; + void *base = *addr; + DWORD dlen = len; + + phys.QuadPart = (ULONGLONG) off; + + if ((ret = NtMapViewOfSection (h, + INVALID_HANDLE_VALUE, + &base, + 0L, + dlen, + &phys, + &dlen, + ViewShare /*??*/, + 0, + protect)) != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + syscall_printf ("-1 = mmap(): NtMapViewOfSection failed with %E"); + return INVALID_HANDLE_VALUE; + } + if ((flags & MAP_FIXED) && base != addr) + { + set_errno (EINVAL); + syscall_printf ("-1 = mmap(): address shift with MAP_FIXED given"); + NtUnmapViewOfSection (INVALID_HANDLE_VALUE, base); + return INVALID_HANDLE_VALUE; + } + + *addr = (caddr_t) base; + return h; +} + +int +fhandler_dev_mem::munmap (HANDLE h, caddr_t addr, size_t len) +{ + NTSTATUS ret; + if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, addr))) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + return -1; + } + CloseHandle (h); + return 0; +} + +int +fhandler_dev_mem::msync (HANDLE h, caddr_t addr, size_t len, int flags) +{ + return 0; +} + int fhandler_dev_mem::fstat (struct stat *buf) { @@ -276,7 +395,7 @@ fhandler_dev_mem::fstat (struct stat *buf) S_IROTH | S_IWOTH; buf->st_nlink = 1; buf->st_blksize = getpagesize (); - buf->st_dev = buf->st_rdev = get_device () << 8; + buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff); return 0; } diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 7c7d84c86f..6beb45a2e5 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -203,7 +203,7 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off) caddr_t base = addr; HANDLE h; - if (fd == -1) + if ((flags & MAP_ANONYMOUS) || fd == -1) { fh_paging_file.set_io_handle (INVALID_HANDLE_VALUE); fh = &fh_paging_file; @@ -463,8 +463,16 @@ fhandler_disk_file::mmap (caddr_t *addr, size_t len, DWORD access, if (!base || ((flags & MAP_FIXED) && base != addr)) { - __seterrno (); - syscall_printf ("-1 = mmap(): MapViewOfFileEx failed with %E"); + if (!base) + { + __seterrno (); + syscall_printf ("-1 = mmap(): MapViewOfFileEx failed with %E"); + } + else + { + set_errno (EINVAL); + syscall_printf ("-1 = mmap(): address shift with MAP_FIXED given"); + } CloseHandle (h); return INVALID_HANDLE_VALUE; } diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 033a0c5c5d..fb8bcd5dd2 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -500,7 +500,15 @@ get_device_number (const char *name, int &unit, BOOL from_conv) unit = 8 + (deveqn ("u", 1) ? 1 : 0); /* Keep unit Linux conformant */ } else if (deveq ("mem")) - devn = FH_MEM; + { + devn = FH_MEM; + unit = 1; + } + else if (deveq ("port")) + { + devn = FH_MEM; + unit = 4; + } else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0) devn = FH_SERIAL; else if (deveq ("pipe") || deveq ("piper") || deveq ("pipew")) -- 2.11.0