From b98442bbfaa0b61963c23c6079055c94515e38dd Mon Sep 17 00:00:00 2001 From: Joey Hewitt Date: Mon, 9 Oct 2017 21:41:43 -0700 Subject: [PATCH] add uio dev support diff --git a/sharedmem.c b/sharedmem.c index f788b8a..eead258 100644 --- a/sharedmem.c +++ b/sharedmem.c @@ -44,6 +44,37 @@ static int parse_hex_sysattr(struct udev_device *dev, const char *name, return 0; } +static int parse_hex_sysfsfile(int dir_fd, const char *name, + unsigned long *value) +{ + unsigned long val; + char buf[32]; + char *endptr; + int fd; + + fd = openat(dir_fd, name, O_RDONLY); + if (fd < 0) { + return -errno; + } + + if (read(fd, buf, sizeof(buf)) < 0) { + close(fd); + return -errno; + } + + close(fd); + + errno = 0; + val = strtoul(buf, &endptr, 16); + if ((val == LONG_MAX && errno == ERANGE) || endptr == buf) { + return -errno; + } + + *value = val; + + return 0; +} + static int rmtfs_mem_open_rfsa(struct rmtfs_mem *rmem, int client_id) { struct udev_device *dev; @@ -114,6 +145,88 @@ err_close_fd: return -saved_errno; } +static int rmtfs_mem_open_uio(struct rmtfs_mem *rmem) +{ + int saved_errno; + char path[64]; + char buf[32]; + int ret; + int dir_fd; + int fd; + + for (int uio_index = 0; uio_index < 8; uio_index++) { + snprintf(path, sizeof(path), "/sys/class/uio/uio%d", uio_index); + dir_fd = open(path, O_DIRECTORY); + if (dir_fd < 0) { + saved_errno = errno; + if (errno != ENOENT) { + fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); + } + goto ret; + } + + fd = openat(dir_fd, "name", O_RDONLY); + if (fd < 0) { + saved_errno = errno; + fprintf(stderr, "failed to open %s/name: %s\n", path, strerror(errno)); + goto close_dirfd; + } + + if (read(fd, buf, sizeof(buf)) < 0) { + saved_errno = errno; + fprintf(stderr, "failed to read %s/name: %s\n", path, strerror(errno)); + close(fd); + goto close_dirfd; + } + + close(fd); + + if (strncmp(buf, "rmtfs\n", 6)) { + continue; + } + + ret = parse_hex_sysfsfile(dir_fd, "maps/map0/addr", &rmem->address); + if (ret < 0) { + fprintf(stderr, "failed to parse addr of %s\n", path); + saved_errno = -ret; + goto close_dirfd; + } + + ret = parse_hex_sysfsfile(dir_fd, "maps/map0/size", &rmem->size); + if (ret < 0) { + fprintf(stderr, "failed to parse size of %s\n", path); + saved_errno = -ret; + goto close_dirfd; + } + + snprintf(path, sizeof(path), "/dev/uio%d", uio_index); + rmem->fd = open(path, O_RDWR); + if (rmem->fd < 0) { + saved_errno = errno; + fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); + goto close_dirfd; + } + + rmem->base = mmap(0, rmem->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (rmem->base == MAP_FAILED) { + saved_errno = errno; + fprintf(stderr, "failed to mmap: %s\n", strerror(errno)); + close(rmem->fd); + goto close_dirfd; + } + + saved_errno = 0; + goto close_dirfd; + } + + saved_errno = ENOENT; + +close_dirfd: + close(dir_fd); +ret: + return -saved_errno; +} + struct rmtfs_mem *rmtfs_mem_open(void) { struct rmtfs_mem *rmem; @@ -131,26 +244,31 @@ struct rmtfs_mem *rmtfs_mem_open(void) if (ret < 0 && ret != -ENOENT) { goto err; } else if (ret < 0) { - fprintf(stderr, "falling back to /dev/mem access\n"); - - ret = rmtfs_mem_enumerate(rmem); - if (ret < 0) - goto err; - - fd = open("/dev/mem", O_RDWR|O_SYNC); - if (fd < 0) { - fprintf(stderr, "failed to open /dev/mem\n"); + ret = rmtfs_mem_open_uio(rmem); + if (ret < 0 && ret != -ENOENT) { goto err; + } else if (ret < 0) { + fprintf(stderr, "falling back to /dev/mem access\n"); + + ret = rmtfs_mem_enumerate(rmem); + if (ret < 0) + goto err; + + fd = open("/dev/mem", O_RDWR|O_SYNC); + if (fd < 0) { + fprintf(stderr, "failed to open /dev/mem\n"); + goto err; + } + + base = mmap(0, rmem->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, rmem->address); + if (base == MAP_FAILED) { + fprintf(stderr, "failed to mmap: %s\n", strerror(errno)); + goto err_close_fd; + } + + rmem->base = base; + rmem->fd = fd; } - - base = mmap(0, rmem->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, rmem->address); - if (base == MAP_FAILED) { - fprintf(stderr, "failed to mmap: %s\n", strerror(errno)); - goto err_close_fd; - } - - rmem->base = base; - rmem->fd = fd; } return rmem;