From f4f898aca065b74b476af4c11423695fefd1de3c Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 4 Oct 2000 17:08:46 +0000 Subject: [PATCH] * fhandler.h (fhandler_dev_mem): Add method `init'. Add members `mem_size' and `init_phase'. * fhandler_mem.cc (init): New function to figure out the size of the physical memory. (open): Add checking for illegal flags. Change usage of access mode. (write): Add intended functionality. (read): Add parameter checking. Eliminate page size constant. Use getpagesize() instead. Don't touch errno and don't create debug output while init() is running. (lseek): Add bounds checking. Fix SEEK_END. (fstat): Eliminate page size constant. Use getpagesize() instead. (dup): Add intended functionality. --- winsup/cygwin/ChangeLog | 17 +++- winsup/cygwin/fhandler.h | 4 + winsup/cygwin/fhandler_mem.cc | 148 +++++++++++++++++++++++++++++----- 3 files changed, 148 insertions(+), 21 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 90550ca56..815d637a3 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +Wed Oct 4 18:48:00 2000 Corinna Vinschen + + * fhandler.h (fhandler_dev_mem): Add method `init'. Add members + `mem_size' and `init_phase'. + * fhandler_mem.cc (init): New function to figure out the size of + the physical memory. + (open): Add checking for illegal flags. Change usage of access mode. + (write): Add intended functionality. + (read): Add parameter checking. Eliminate page size constant. Use + getpagesize() instead. Don't touch errno and don't create debug output + while init() is running. + (lseek): Add bounds checking. Fix SEEK_END. + (fstat): Eliminate page size constant. Use getpagesize() instead. + (dup): Add intended functionality. + Mon Oct 2 22:15:00 2000 Corinna Vinschen * dcrt0.cc: Add LoadDLLFunc statement for RegEnumValueA(). @@ -5,7 +20,7 @@ Mon Oct 2 22:15:00 2000 Corinna Vinschen (get_2k_ifconf): Eliminate `type' variable. Eliminate `sa' parameter. (get_nt_ifconf): Ditto. (get_9x_ifconf): Ditto. Rewritten. - (get_ifconf): Chage calls to OS specific functions. + (get_ifconf): Change calls to OS specific functions. Mon Oct 2 15:15:01 2000 Christopher Faylor diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 41f5829d4..36604519e 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -767,7 +767,11 @@ public: class fhandler_dev_mem: public fhandler_base { protected: + unsigned long mem_size; unsigned long pos; + bool init_phase; + + void init (void); public: fhandler_dev_mem (const char *name, int unit); diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc index 50370d876..10213e656 100644 --- a/winsup/cygwin/fhandler_mem.cc +++ b/winsup/cygwin/fhandler_mem.cc @@ -36,7 +36,7 @@ ULONG NTAPI RtlNtStatusToDosError(NTSTATUS); fhandler_dev_mem::fhandler_dev_mem (const char *name, int) : fhandler_base (FH_MEM, name), - pos(0UL) + init_phase(false) { } @@ -44,6 +44,30 @@ 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 (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); + init_phase = false; +} + int fhandler_dev_mem::open (const char *, int flags, mode_t) { @@ -54,21 +78,38 @@ fhandler_dev_mem::open (const char *, int flags, mode_t) return 0; } + /* Check for illegal flags. */ + if (flags & (O_APPEND | O_TRUNC | O_EXCL)) + { + set_errno (EINVAL); + return 0; + } + UNICODE_STRING memstr; RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory"); OBJECT_ATTRIBUTES attr; InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL); + ACCESS_MASK section_access; if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) - set_access (SECTION_MAP_READ); + { + set_access (GENERIC_READ); + section_access = SECTION_MAP_READ; + } else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) - set_access (SECTION_MAP_WRITE); + { + set_access (GENERIC_WRITE); + section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; + } else - set_access (SECTION_MAP_READ | SECTION_MAP_WRITE); + { + set_access (GENERIC_READ | GENERIC_WRITE); + section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; + } HANDLE mem; - NTSTATUS ret = NtOpenSection (&mem, get_access (), &attr); + NTSTATUS ret = NtOpenSection (&mem, section_access, &attr); if (!NT_SUCCESS(ret)) { __seterrno_from_win_error (RtlNtStatusToDosError (ret)); @@ -77,26 +118,29 @@ fhandler_dev_mem::open (const char *, int flags, mode_t) } set_io_handle (mem); + init (); return 1; } int -fhandler_dev_mem::write (const void *ptr, size_t len) +fhandler_dev_mem::write (const void *ptr, size_t ulen) { - set_errno (ENOSYS); - return -1; -} - -int -fhandler_dev_mem::read (void *ptr, size_t ulen) -{ - if (!ulen) + if (!ulen || pos >= mem_size) return 0; + if (!(get_access () & GENERIC_WRITE)) + { + set_errno (EINVAL); + return -1; + } + + if (pos + ulen > mem_size) + ulen = mem_size - pos; + PHYSICAL_ADDRESS phys; NTSTATUS ret; void *viewmem = NULL; - DWORD len = ulen + 4095; + DWORD len = ulen + getpagesize () - 1; phys.QuadPart = (ULONGLONG) pos; if ((ret = NtMapViewOfSection (get_handle (), @@ -114,6 +158,56 @@ fhandler_dev_mem::read (void *ptr, size_t ulen) return -1; } + memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, 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::read (void *ptr, size_t ulen) +{ + if (!ulen || pos >= mem_size) + return 0; + + if (!(get_access () & GENERIC_READ)) + { + set_errno (EINVAL); + return -1; + } + + if (pos + ulen > mem_size) + ulen = mem_size - pos; + + PHYSICAL_ADDRESS phys; + NTSTATUS ret; + void *viewmem = NULL; + DWORD len = ulen + getpagesize () - 1; + + phys.QuadPart = (ULONGLONG) pos; + if ((ret = NtMapViewOfSection (get_handle (), + INVALID_HANDLE_VALUE, + &viewmem, + 0L, + len, + &phys, + &len, + ViewShare, + 0, + PAGE_READONLY)) != STATUS_SUCCESS) + { + if (!init_phase) /* Don't want to flood debug output with init crap. */ + __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))) @@ -147,8 +241,8 @@ fhandler_dev_mem::lseek (off_t offset, int whence) break; case SEEK_END: - pos = 0; - pos -= offset; + pos = mem_size; + pos += offset; break; default: @@ -156,6 +250,12 @@ fhandler_dev_mem::lseek (off_t offset, int whence) return (off_t) -1; } + if (pos > mem_size) + { + set_errno (EINVAL); + return (off_t) -1; + } + return pos; } @@ -175,7 +275,7 @@ fhandler_dev_mem::fstat (struct stat *buf) S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; buf->st_nlink = 1; - buf->st_blksize = 4096; + buf->st_blksize = getpagesize (); buf->st_dev = buf->st_rdev = get_device () << 8; return 0; @@ -184,8 +284,16 @@ fhandler_dev_mem::fstat (struct stat *buf) int fhandler_dev_mem::dup (fhandler_base *child) { - set_errno (ENOSYS); - return -1; + int ret = fhandler_base::dup (child); + + if (! ret) + { + fhandler_dev_mem *fhc = (fhandler_dev_mem *) child; + + fhc->mem_size = mem_size; + fhc->pos = pos; + } + return ret; } void