From 70caff20e2a4a6d3a913cef120c0e53c93eed68e Mon Sep 17 00:00:00 2001 From: "Vanya A. Sergeev" Date: Tue, 1 Dec 2020 23:58:49 -0600 Subject: [PATCH] mmio: add advanced open function for alternate device path --- docs/mmio.md | 30 +++++++++++++++++++++--------- src/mmio.c | 10 +++++++--- src/mmio.h | 1 + 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/docs/mmio.md b/docs/mmio.md index 8884ba0..49542f3 100644 --- a/docs/mmio.md +++ b/docs/mmio.md @@ -10,6 +10,7 @@ MMIO wrapper functions for the Linux userspace `/dev/mem` device. /* Primary Functions */ mmio_t *mmio_new(void); int mmio_open(mmio_t *mmio, uintptr_t base, size_t size); +int mmio_open_advanced(mmio_t *mmio, uintptr_t base, size_t size, const char *path); void *mmio_ptr(mmio_t *mmio); int mmio_read32(mmio_t *mmio, uintptr_t offset, uint32_t *value); int mmio_read16(mmio_t *mmio, uintptr_t offset, uint16_t *value); @@ -46,7 +47,18 @@ Returns a valid handle on success, or NULL on failure. ``` c int mmio_open(mmio_t *mmio, uintptr_t base, size_t size); ``` -Map the region of physical memory at the specified base address with the specified size. +Map the region of physical memory specified by the `base` physical address and `size` size in bytes, using the default `/dev/mem` memory character device. + +`mmio` should be a valid pointer to an allocated MMIO handle structure. Neither `base` nor `size` need be aligned to a page boundary. + +Returns 0 on success, or a negative [MMIO error code](#return-value) on failure. + +------ + +``` c +int mmio_open_advanced(mmio_t *mmio, uintptr_t base, size_t size, const char *path); +``` +Map the region of physical memory specified by the `base` physical address and `size` size in bytes, using the specified memory character device. This open function can be used with sandboxed memory character devices, e.g. `/dev/gpiomem`. `mmio` should be a valid pointer to an allocated MMIO handle structure. Neither `base` nor `size` need be aligned to a page boundary. @@ -71,7 +83,7 @@ int mmio_read(mmio_t *mmio, uintptr_t offset, uint8_t *buf, size_t len); ``` Read 32-bits, 16-bits, 8-bits, or an array of bytes, respectively, from mapped physical memory, starting at the specified byte offset, relative to the base address the MMIO handle was opened with. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. Returns 0 on success, or a negative [MMIO error code](#return-value) on failure. @@ -85,7 +97,7 @@ int mmio_write(mmio_t *mmio, uintptr_t offset, const uint8_t *buf, size_t len); ``` Write 32-bits, 16-bits, 8-bits, or an array of bytes, respectively, to mapped physical memory, starting at the specified byte offset, relative to the base address the MMIO handle was opened with. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. Returns 0 on success, or a negative [MMIO error code](#return-value) on failure. @@ -96,7 +108,7 @@ int mmio_close(mmio_t *mmio); ``` Unmap mapped physical memory. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. Returns 0 on success, or a negative [MMIO error code](#return-value) on failure. @@ -114,7 +126,7 @@ uintptr_t mmio_base(mmio_t *mmio); ``` Return the base address the MMIO handle was opened with. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. This function is a simple accessor to the MMIO handle structure and always succeeds. @@ -125,7 +137,7 @@ size_t mmio_size(mmio_t *mmio); ``` Return the size the MMIO handle was opened with. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. This function is a simple accessor to the MMIO handle structure and always succeeds. @@ -136,7 +148,7 @@ int mmio_tostring(mmio_t *mmio, char *str, size_t len); ``` Return a string representation of the MMIO handle. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. This function behaves and returns like `snprintf()`. @@ -147,7 +159,7 @@ int mmio_errno(mmio_t *mmio); ``` Return the libc errno of the last failure that occurred. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. ------ @@ -156,7 +168,7 @@ const char *mmio_errmsg(mmio_t *mmio); ``` Return a human readable error message of the last failure that occurred. -`mmio` should be a valid pointer to an MMIO handle opened with `mmio_open()`. +`mmio` should be a valid pointer to an MMIO handle opened with one of the `mmio_open*()` functions. ### RETURN VALUE diff --git a/src/mmio.c b/src/mmio.c index a8e238f..34f8d69 100644 --- a/src/mmio.c +++ b/src/mmio.c @@ -57,6 +57,10 @@ void mmio_free(mmio_t *mmio) { } int mmio_open(mmio_t *mmio, uintptr_t base, size_t size) { + return mmio_open_advanced(mmio, base, size, "/dev/mem"); +} + +int mmio_open_advanced(mmio_t *mmio, uintptr_t base, size_t size, const char *path) { int fd; memset(mmio, 0, sizeof(mmio_t)); @@ -66,8 +70,8 @@ int mmio_open(mmio_t *mmio, uintptr_t base, size_t size) { mmio->aligned_size = mmio->size + (mmio->base - mmio->aligned_base); /* Open memory */ - if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) - return _mmio_error(mmio, MMIO_ERROR_OPEN, errno, "Opening /dev/mem"); + if ((fd = open(path, O_RDWR | O_SYNC)) < 0) + return _mmio_error(mmio, MMIO_ERROR_OPEN, errno, "Opening %s", path); /* Map memory */ if ((mmio->ptr = mmap(0, mmio->aligned_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmio->aligned_base)) == MAP_FAILED) { @@ -81,7 +85,7 @@ int mmio_open(mmio_t *mmio, uintptr_t base, size_t size) { int errsv = errno; munmap(mmio->ptr, mmio->aligned_size); mmio->ptr = 0; - return _mmio_error(mmio, MMIO_ERROR_OPEN, errsv, "Closing /dev/mem"); + return _mmio_error(mmio, MMIO_ERROR_OPEN, errsv, "Closing %s", path); } return 0; diff --git a/src/mmio.h b/src/mmio.h index c64454a..64be152 100644 --- a/src/mmio.h +++ b/src/mmio.h @@ -26,6 +26,7 @@ typedef struct mmio_handle mmio_t; /* Primary Functions */ mmio_t *mmio_new(void); int mmio_open(mmio_t *mmio, uintptr_t base, size_t size); +int mmio_open_advanced(mmio_t *mmio, uintptr_t base, size_t size, const char *path); void *mmio_ptr(mmio_t *mmio); int mmio_read32(mmio_t *mmio, uintptr_t offset, uint32_t *value); int mmio_read16(mmio_t *mmio, uintptr_t offset, uint16_t *value);