Created
September 21, 2026 10:05
-
-
Save faveoled/e97c9abfa9262bf11048f2c1215fd1d4 to your computer and use it in GitHub Desktop.
Fill FB pixels using /dev/mem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import mmap | |
| import os | |
| class FbWriter: | |
| PAGE_SIZE = os.sysconf('SC_PAGESIZE') | |
| DEV_MEM = "/dev/mem" | |
| def __init__(self): | |
| """ | |
| Initializes the writer by mapping /dev/mem. | |
| :param size: Number of bytes to map. | |
| :param offset: The physical address start (must be a multiple of PAGE_SIZE). | |
| """ | |
| self.fd = os.open(self.DEV_MEM, os.O_RDWR | os.O_SYNC) | |
| def do_writes(self, start_addr: int, total_size: int, color: bytes): | |
| end_addr_exclusive = start_addr + total_size | |
| current_addr = start_addr | |
| while current_addr < end_addr_exclusive: | |
| current_page_start_addr = (current_addr // FbWriter.PAGE_SIZE) * FbWriter.PAGE_SIZE | |
| next_page_start_addr_exclusive = current_page_start_addr + FbWriter.PAGE_SIZE | |
| writes_remaining = end_addr_exclusive - current_addr | |
| if current_page_start_addr != current_addr: | |
| # first half-page | |
| writes_end_exclusive = min(end_addr_exclusive, next_page_start_addr_exclusive) | |
| self._do_single_byte_writes(current_addr, writes_end_exclusive, color) | |
| current_addr = writes_end_exclusive | |
| elif writes_remaining > FbWriter.PAGE_SIZE or writes_remaining % FbWriter.PAGE_SIZE == 0: | |
| # middle full page | |
| self._do_full_page_write(current_addr, current_addr + FbWriter.PAGE_SIZE, color) | |
| current_addr = current_addr + FbWriter.PAGE_SIZE | |
| elif writes_remaining % FbWriter.PAGE_SIZE != 0: | |
| # last half-page | |
| self._do_single_byte_writes(current_addr, end_addr_exclusive, color) | |
| current_addr = end_addr_exclusive | |
| else: | |
| raise RuntimeError("Bug") | |
| def _do_full_page_write(self, start_addr: int, end_addr_exclusive: int, color: bytes): | |
| print(f"Full page write {hex(start_addr)}-{hex(end_addr_exclusive)}") | |
| to_write = end_addr_exclusive - start_addr | |
| mm = mmap.mmap(self.fd, FbWriter.PAGE_SIZE, mmap.MAP_SHARED, mmap.PROT_WRITE | mmap.PROT_READ, offset=start_addr) | |
| mm[0:to_write] = color * to_write | |
| mm.close() | |
| def _do_single_byte_writes(self, start_addr: int, end_addr_exclusive: int, color: bytes): | |
| print(f"Writing single bytes {hex(start_addr)}-{hex(end_addr_exclusive)}") | |
| current_page_start_addr = (start_addr // FbWriter.PAGE_SIZE) * FbWriter.PAGE_SIZE | |
| inner_offset = start_addr - current_page_start_addr | |
| mm = mmap.mmap(self.fd, FbWriter.PAGE_SIZE, mmap.MAP_SHARED, mmap.PROT_WRITE | mmap.PROT_READ, offset=current_page_start_addr) | |
| to_write = end_addr_exclusive - start_addr | |
| payload = color * to_write | |
| for i in range(to_write): | |
| mm[inner_offset + i] = payload[i] | |
| mm.close() | |
| def close(self): | |
| os.close(self.fd) | |
| # Usage Example: | |
| writer = FbWriter() | |
| writer.do_writes(0xbee00000, 921600, b'\xcc') | |
| writer.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment