Skip to content

Commit

Permalink
mmio: add advanced open function for alternate device path
Browse files Browse the repository at this point in the history
  • Loading branch information
vsergeev committed Dec 16, 2020
1 parent 513f5ed commit 70caff2
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
30 changes: 21 additions & 9 deletions docs/mmio.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.

Expand All @@ -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.

Expand All @@ -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.
Expand All @@ -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.

Expand All @@ -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.

Expand All @@ -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.
Expand All @@ -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()`.

Expand All @@ -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.
------
Expand All @@ -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

Expand Down
10 changes: 7 additions & 3 deletions src/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/mmio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 70caff2

Please sign in to comment.