Luc Verhaegen has uploaded this change for review. ( https://review.coreboot.org/29079
Change subject: pci2: add mmio bar map/unmap ......................................................................
pci2: add mmio bar map/unmap
This works through linux sysfs and opens /sys/bus/pci/devices/.../resource%d and maps that to neatly circumvent /dev/mem security limitations and we do not need to figure out BAR address and size ourselves.
Change-Id: I1c67d51d853f751d13271bf83316ee2118c1c476 Signed-off-by: Luc Verhaegen libv@skynet.be --- M pcidev.c M programmer.h 2 files changed, 75 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/79/29079/1
diff --git a/pcidev.c b/pcidev.c index 837b028..8503e78 100644 --- a/pcidev.c +++ b/pcidev.c @@ -18,6 +18,11 @@
#include <stdlib.h> #include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <unistd.h> + #include "flash.h" #include "programmer.h" #include "hwaccess.h" @@ -352,6 +357,69 @@ /* * */ +int +flashrom_pci_mmio_map(struct flashrom_pci_device *device, int bar) +{ + char filename[1024]; + int fd; + + if ((bar < 0) || (bar > 5)) { + msg_perr("%s: Invalid BAR provided: %d\n", __func__, bar); + return EINVAL; + } + + if (device->mmio) { + if (device->pci->size[bar] != device->mmio_size) { + msg_perr("%s: already mapped bar: 0x%lXbytes @ %p)\n", + __func__, device->mmio_size, device->mmio); + return EALREADY; + } else + return 0; + } + + snprintf(filename, sizeof(filename) - 1, + "%sresource%d", device->sysfs_path, bar); + + fd = open(filename, O_RDWR); + if (fd == -1) { + msg_perr("%s: failed to open %s: %s\n", + __func__, filename, strerror(errno)); + return errno; + } + + device->mmio_size = device->pci->size[bar]; + + device->mmio = mmap(NULL, device->mmio_size, PROT_WRITE | PROT_READ, + MAP_SHARED, fd, 0); + if (device->mmio == MAP_FAILED) { + msg_perr("%s: mapping %s failed: %s\n", + __func__, filename, strerror(errno)); + close(fd); + device->mmio_size = 0; + return errno; + } + + close(fd); + + return 0; +} + +/* + * + */ +void +flashrom_pci_mmio_unmap(struct flashrom_pci_device *device) +{ + if (device->mmio && device->mmio_size && + (device->mmio != MAP_FAILED)) + munmap((void *) device->mmio, device->mmio_size); + device->mmio = NULL; + device->mmio_size = 0; +} + +/* + * + */ static int flashrom_pci_device_shutdown(void *data) { @@ -363,6 +431,8 @@ return 1; }
+ flashrom_pci_mmio_unmap(device); + free(device->sysfs_path); device->sysfs_path = NULL;
diff --git a/programmer.h b/programmer.h index 0a445fa..d553317 100644 --- a/programmer.h +++ b/programmer.h @@ -868,10 +868,15 @@
char *sysfs_path; /* linux only, of course */
+ volatile uint8_t *mmio; /* mapped io memory */ + size_t mmio_size; + const void *private; /* programmer specific hook */ };
struct flashrom_pci_device *flashrom_pci_init(const struct flashrom_pci_match *matches); +int flashrom_pci_mmio_map(struct flashrom_pci_device *device, int bar); +void flashrom_pci_mmio_unmap(struct flashrom_pci_device *device); #endif /* NEED_PCI */
#endif /* !__PROGRAMMER_H__ */