diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 1615cda0e..8d9569945 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +Sun Oct 1 2:56:00 2000 Corinna Vinschen + + * Makefile.in: Add fhandler_mem.o to the dependencies. + * dtable.cc (dtable::build_fhandler): Add case for FH_MEM. + * fhandler.h: Add FH_MEM device type. Add class fhandler_dev_mem. + * fhandler_mem.cc: New file. Implementation of class fhandler_dev_mem. + * path.cc: Add /dev/mem to windows_device_names. + (get_device_number): Add FH_MEM type. + Sat Sep 30 00:43:42 2000 Christopher Faylor * cygheap.cc (init_cheap): Set aside space for heap walk pointer. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 659cb22cc..a5a780e24 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -119,7 +119,7 @@ DLL_IMPORTS:=$(w32api_lib)/libkernel32.a DLL_OFILES:=assert.o cygheap.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o \ dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \ - fcntl.o fhandler.o fhandler_console.o fhandler_floppy.o \ + fcntl.o fhandler.o fhandler_console.o fhandler_floppy.o fhandler_mem.o \ fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_tape.o \ fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \ fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o mmap.o \ diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index b2a765a3e..5eff4fd66 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -296,6 +296,9 @@ dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit) case FH_RANDOM: fh = new (buf) fhandler_dev_random (name, unit); break; + case FH_MEM: + fh = new (buf) fhandler_dev_mem (name, unit); + break; default: /* FIXME - this could recurse forever */ return build_fhandler (fd, name, NULL); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index d3fc19565..41f5829d4 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -41,6 +41,8 @@ details. */ fhandler_dev_random /dev/[u]random implementation (fhandler_random.cc) + fhandler_dev_mem /dev/mem implementation (fhandler_mem.cc) + fhandler_proc Interesting possibility, not implemented yet */ @@ -94,8 +96,9 @@ enum FH_NULL = 0x00000013, /* is the null device */ FH_ZERO = 0x00000014, /* is the zero device */ FH_RANDOM = 0x00000015, /* is a random device */ + FH_MEM = 0x00000016, /* is a mem device */ - FH_NDEV = 0x00000016, /* Maximum number of devices */ + FH_NDEV = 0x00000017, /* Maximum number of devices */ FH_DEVMASK = 0x00000fff, /* devices live here */ FH_BAD = 0xffffffff }; @@ -761,6 +764,26 @@ public: void dump (); }; +class fhandler_dev_mem: public fhandler_base +{ +protected: + unsigned long pos; + +public: + fhandler_dev_mem (const char *name, int unit); + ~fhandler_dev_mem (void); + + int open (const char *path, int flags, mode_t mode = 0); + int write (const void *ptr, size_t ulen); + int read (void *ptr, size_t ulen); + off_t lseek (off_t offset, int whence); + int close (void); + int fstat (struct stat *buf); + int dup (fhandler_base *child); + + void dump (); +}; + class fhandler_windows: public fhandler_base { private: diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc new file mode 100644 index 000000000..7d26bd469 --- /dev/null +++ b/winsup/cygwin/fhandler_mem.cc @@ -0,0 +1,260 @@ +/* fhandler_mem.cc. See fhandler.h for a description of the fhandler classes. + + Copyright 1999, 2000 Cygnus Solutions. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +#include "winsup.h" +#include +#include +#include +#include +#include + +#include "cygheap.h" +#include "cygerrno.h" +#include "fhandler.h" +#include "path.h" + +static int inited = FALSE; +NTSTATUS (__stdcall *NtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG,ULONG, + PLARGE_INTEGER,PULONG,SECTION_INHERIT, + ULONG,ULONG); +NTSTATUS (__stdcall *NtOpenSection)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES); +NTSTATUS (__stdcall *NtUnmapViewOfSection)(HANDLE,PVOID); +VOID (__stdcall *RtlInitUnicodeString)(PUNICODE_STRING,PCWSTR); +ULONG (__stdcall *RtlNtStatusToDosError) (NTSTATUS); + +int +load_ntdll_funcs () +{ + int ret = 0; + + if (os_being_run != winNT) + { + set_errno (ENOENT); + debug_printf ("/dev/mem is accessible under NT/W2K only"); + return 0; + } + + HMODULE ntdll = GetModuleHandle ("ntdll.dll"); + + if (inited) + { + debug_printf ("function pointers already inited"); + return 1; + } + + if (!ntdll) + { + __seterrno (); + goto out; + } + + if (!(NtMapViewOfSection = (NTSTATUS (*)(HANDLE,HANDLE,PVOID*,ULONG,ULONG, + PLARGE_INTEGER,PULONG, + SECTION_INHERIT,ULONG,ULONG)) + GetProcAddress (ntdll, "NtMapViewOfSection"))) + { + __seterrno (); + goto out; + } + + if (!(NtOpenSection = (NTSTATUS (*)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES)) + GetProcAddress (ntdll, "NtOpenSection"))) + { + __seterrno (); + goto out; + } + + if (!(NtUnmapViewOfSection = (NTSTATUS (*)(HANDLE,PVOID)) + GetProcAddress (ntdll, "NtUnmapViewOfSection"))) + { + __seterrno (); + goto out; + } + + if (!(RtlInitUnicodeString = (VOID (*)(PUNICODE_STRING,PCWSTR)) + GetProcAddress (ntdll, "RtlInitUnicodeString"))) + { + __seterrno (); + goto out; + } + + if (!(RtlNtStatusToDosError = (ULONG (*)(NTSTATUS)) + GetProcAddress (ntdll, "RtlNtStatusToDosError"))) + { + __seterrno (); + goto out; + } + + inited = TRUE; + ret = 1; + +out: + debug_printf ("%d = load_ntdll_funcs()", ret); + return ret; +} + +/**********************************************************************/ +/* fhandler_dev_mem */ + +fhandler_dev_mem::fhandler_dev_mem (const char *name, int) +: fhandler_base (FH_MEM, name), + pos(0UL) +{ +} + +fhandler_dev_mem::~fhandler_dev_mem (void) +{ +} + +int +fhandler_dev_mem::open (const char *, int flags, mode_t) +{ + if (!load_ntdll_funcs ()) + return 0; + + UNICODE_STRING memstr; + RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory"); + + OBJECT_ATTRIBUTES attr; + InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL); + + if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) + set_access (SECTION_MAP_READ); + else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) + set_access (SECTION_MAP_WRITE); + else + set_access (SECTION_MAP_READ | SECTION_MAP_WRITE); + + HANDLE mem; + NTSTATUS ret = NtOpenSection (&mem, get_access (), &attr); + if (!NT_SUCCESS(ret)) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + set_io_handle (NULL); + return 0; + } + + set_io_handle (mem); + return 1; +} + +int +fhandler_dev_mem::write (const void *ptr, size_t len) +{ + set_errno (ENOSYS); + return -1; +} + +int +fhandler_dev_mem::read (void *ptr, size_t ulen) +{ + if (!ulen) + return 0; + + PHYSICAL_ADDRESS phys; + NTSTATUS ret; + void *viewmem = NULL; + DWORD len = ulen + 4095; + + phys.QuadPart = (ULONGLONG) pos; + if ((ret = NtMapViewOfSection (get_handle (), + INVALID_HANDLE_VALUE, + &viewmem, + 0L, + len, + &phys, + &len, + ViewShare, + 0, + PAGE_READONLY)) != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + return -1; + } + + memcpy (ptr, (char *) viewmem + (pos - phys.QuadPart), ulen); + + if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem))) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + return -1; + } + + pos += ulen; + + return ulen; +} + +int +fhandler_dev_mem::close (void) +{ + return fhandler_base::close (); +} + +off_t +fhandler_dev_mem::lseek (off_t offset, int whence) +{ + switch (whence) + { + case SEEK_SET: + pos = offset; + break; + + case SEEK_CUR: + pos += offset; + break; + + case SEEK_END: + pos = 0; + pos -= offset; + break; + + default: + set_errno (EINVAL); + return (off_t) -1; + } + + return pos; +} + +int +fhandler_dev_mem::fstat (struct stat *buf) +{ + if (!buf) + { + set_errno (EINVAL); + return -1; + } + + memset (buf, 0, sizeof *buf); + buf->st_mode = S_IFCHR; + if (os_being_run != winNT) + buf->st_mode |= S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH; + buf->st_nlink = 1; + buf->st_blksize = 4096; + buf->st_dev = buf->st_rdev = get_device () << 8; + + return 0; +} + +int +fhandler_dev_mem::dup (fhandler_base *child) +{ + set_errno (ENOSYS); + return -1; +} + +void +fhandler_dev_mem::dump () +{ + paranoid_printf("here, fhandler_dev_mem"); +} diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 759ca3720..856bdeff5 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -417,6 +417,7 @@ const char *windows_device_names[] = "nul", "\\dev\\zero", "\\dev\\%srandom", + "\\dev\\mem", }; static int @@ -486,6 +487,8 @@ get_device_number (const char *name, int &unit, BOOL from_conv) devn = FH_RANDOM; unit = 8 + (deveqn ("u", 1) ? 1 : 0); /* Keep unit Linux conformant */ } + else if (deveq ("mem")) + devn = FH_MEM; else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0) devn = FH_SERIAL; else if (deveq ("pipe") || deveq ("piper") || deveq ("pipew"))