diff options
author | Bastian Stender <bst@pengutronix.de> | 2016-07-15 14:40:08 +0200 |
---|---|---|
committer | Markus Pargmann <mpa@pengutronix.de> | 2016-07-15 14:45:44 +0200 |
commit | e932629ed47c800060c8e6f9a4750cef3b87b21f (patch) | |
tree | 3091366d45bb0c9ca6fa002d1bb4f78daa6245f7 | |
parent | b8d0b6f71835790ed2af22d72d3df55a734b9278 (diff) | |
download | dt-utils-e932629ed47c800060c8e6f9a4750cef3b87b21f.tar.gz dt-utils-e932629ed47c800060c8e6f9a4750cef3b87b21f.tar.xz |
libdt: add block devicepath extraction
This allows barebox state to find the backend node on block
devices.
This is a reworked version of the patch. The outdated patch
did not specify the parent correctly resulting in an
incorrect subtree. This lead to the wrong block device
being returned.
Signed-off-by: Bastian Stender <bst@pengutronix.de>
-rw-r--r-- | src/libdt.c | 79 |
1 files changed, 71 insertions, 8 deletions
diff --git a/src/libdt.c b/src/libdt.c index 7a1fb55..a509878 100644 --- a/src/libdt.c +++ b/src/libdt.c @@ -2028,6 +2028,61 @@ static struct udev_device *device_find_mtd_partition(struct udev_device *dev, } /* + * device_find_block_device - extract device path from udev block device + * + * @dev: the udev_device to extract information from + * @devpath: returns the devicepath under which the block device is accessible + * + * returns 0 for success or negative error value on failure. + */ +int device_find_block_device(struct udev_device *dev, + char **devpath) +{ + + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *part; + const char *outpath; + int ret; + + udev = udev_new(); + if (!udev) { + fprintf(stderr, "Can't create udev\n"); + return -ENODEV; + } + + enumerate = udev_enumerate_new(udev); + /* block device and partitions get identified by subsystem in subtree */ + udev_enumerate_add_match_parent(enumerate, dev); + udev_enumerate_add_match_subsystem(enumerate, "block"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path, *devtype; + path = udev_list_entry_get_name(dev_list_entry); + part = udev_device_new_from_syspath(udev, path); + /* distinguish device (disk) from partitions */ + devtype = udev_device_get_devtype(part); + if (!devtype) + continue; + if (!strcmp(devtype, "disk")) { + outpath = udev_device_get_devnode(part); + *devpath = strdup(outpath); + ret = 0; + goto out; + } + } + ret = -ENODEV; + +out: + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return ret; +} + +/* * of_parse_partition - extract offset and size from a partition device_node * * returns true for success, negative error code otherwise @@ -2209,10 +2264,11 @@ out: * This function takes a device_node which represents a partition. * For this partition the function returns the device path and the offset * and size in the device. For mtd devices the path will be /dev/mtdx, for - * EEPROMs it will be /sys/.../eeprom. For mtd devices the device path returned - * will be the partition itself. Since EEPROMs do not have partitions under - * Linux @offset and @size will describe the offset and size inside the full - * device. + * EEPROMs it will be /sys/.../eeprom and for block devices it will be /dev/... + * For mtd devices the device path returned will be the partition itself. + * Since EEPROMs do not have partitions under Linux @offset and @size will + * describe the offset and size inside the full device. The same applies to + * block devices. * * returns 0 for success or negative error value on failure. */ @@ -2234,11 +2290,18 @@ int of_get_devicepath(struct device_node *partition_node, char **devpath, off_t * an out-of-tree kernel patch. */ dev = of_find_device_by_node_path(partition_node->full_name); - if (dev) - if (udev_device_is_eeprom(dev)) + if (dev) { + if (udev_device_is_eeprom(dev)) { return udev_parse_eeprom(dev, devpath); - else - return udev_parse_mtd(dev, devpath, size); + } else { + /* try to find a block device */ + ret = device_find_block_device(dev, devpath); + if (!ret) + return of_parse_partition(partition_node, offset, size); + else + return udev_parse_mtd(dev, devpath, size); + } + } /* * Ok, the partition node has no udev_device. Try parent node. |