From 41d58438aba21d2a74c6f54855e1abd8cb1ad2e4 Mon Sep 17 00:00:00 2001 From: erpalma Date: Fri, 29 Jun 2018 14:52:24 +0200 Subject: [PATCH] included a stripped down version of mmio to avoid python-periphery dependency --- install.sh | 2 +- lenovo_fix.py | 2 +- mmio.py | 120 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 - 4 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 mmio.py diff --git a/install.sh b/install.sh index 7f9b232..97e5b46 100755 --- a/install.sh +++ b/install.sh @@ -20,7 +20,7 @@ echo "Copying systemd service file..." cp systemd/lenovo_fix.service /etc/systemd/system echo "Building virtualenv..." -cp requirements.txt lenovo_fix.py "$INSTALL_DIR" +cp requirements.txt lenovo_fix.py mmio.py "$INSTALL_DIR" cd "$INSTALL_DIR" virtualenv -p /usr/bin/python3 venv . venv/bin/activate diff --git a/lenovo_fix.py b/lenovo_fix.py index 2550472..2c6a24b 100755 --- a/lenovo_fix.py +++ b/lenovo_fix.py @@ -10,8 +10,8 @@ import subprocess from collections import defaultdict from dbus.mainloop.glib import DBusGMainLoop +from mmio import MMIO from multiprocessing import cpu_count -from periphery import MMIO from threading import Event, Thread try: diff --git a/mmio.py b/mmio.py new file mode 100644 index 0000000..0aadeed --- /dev/null +++ b/mmio.py @@ -0,0 +1,120 @@ +''' +Stripped down version from https://github.com/vsergeev/python-periphery/blob/master/periphery/mmio.py +''' +import mmap +import os +import struct +import sys + +# Alias long to int on Python 3 +if sys.version_info[0] >= 3: + long = int + + +class MMIOError(IOError): + """Base class for MMIO errors.""" + pass + + +class MMIO(object): + def __init__(self, physaddr, size): + """Instantiate an MMIO object and map the region of physical memory + specified by the address base `physaddr` and size `size` in bytes. + Args: + physaddr (int, long): base physical address of memory region. + size (int, long): size of memory region. + Returns: + MMIO: MMIO object. + Raises: + MMIOError: if an I/O or OS error occurs. + TypeError: if `physaddr` or `size` types are invalid. + """ + self.mapping = None + self._open(physaddr, size) + + def __del__(self): + self.close() + + def __enter__(self): + pass + + def __exit__(self, t, value, traceback): + self.close() + + def _open(self, physaddr, size): + if not isinstance(physaddr, (int, long)): + raise TypeError("Invalid physaddr type, should be integer.") + if not isinstance(size, (int, long)): + raise TypeError("Invalid size type, should be integer.") + + pagesize = os.sysconf(os.sysconf_names['SC_PAGESIZE']) + + self._physaddr = physaddr + self._size = size + self._aligned_physaddr = physaddr - (physaddr % pagesize) + self._aligned_size = size + (physaddr - self._aligned_physaddr) + + try: + fd = os.open("/dev/mem", os.O_RDWR | os.O_SYNC) + except OSError as e: + raise MMIOError(e.errno, "Opening /dev/mem: " + e.strerror) + + try: + self.mapping = mmap.mmap( + fd, + self._aligned_size, + flags=mmap.MAP_SHARED, + prot=mmap.PROT_WRITE, + offset=self._aligned_physaddr) + except OSError as e: + raise MMIOError(e.errno, "Mapping /dev/mem: " + e.strerror) + + try: + os.close(fd) + except OSError as e: + raise MMIOError(e.errno, "Closing /dev/mem: " + e.strerror) + + # Methods + + def _adjust_offset(self, offset): + return offset + (self._physaddr - self._aligned_physaddr) + + def _validate_offset(self, offset, length): + if (offset + length) > self._aligned_size: + raise ValueError("Offset out of bounds.") + + def write32(self, offset, value): + """Write 32-bits to the specified `offset` in bytes, relative to the + base physical address of the MMIO region. + Args: + offset (int, long): offset from base physical address, in bytes. + value (int, long): 32-bit value to write. + Raises: + TypeError: if `offset` or `value` type are invalid. + ValueError: if `offset` or `value` are out of bounds. + """ + if not isinstance(offset, (int, long)): + raise TypeError("Invalid offset type, should be integer.") + if not isinstance(value, (int, long)): + raise TypeError("Invalid value type, should be integer.") + if value < 0 or value > 0xffffffff: + raise ValueError("Value out of bounds.") + + offset = self._adjust_offset(offset) + self._validate_offset(offset, 4) + self.mapping[offset:offset + 4] = struct.pack("=L", value) + + def close(self): + """Unmap the MMIO object's mapped physical memory.""" + if self.mapping is None: + return + + self.mapping.close() + self.mapping = None + + self._fd = None + + # String representation + + def __str__(self): + return "MMIO 0x%08x (size=%d)" % (self.base, self.size) diff --git a/requirements.txt b/requirements.txt index 4a604f6..f6c7880 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,3 @@ configparser==3.5.0 dbus-python==1.2.8 psutil==5.4.6 PyGObject==3.28.3 -python-periphery==1.1.1