brintos

brintos / linux-shallow public Read only

0
0
Text · 1.6 KiB · 780fd82 Raw
84 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Linux kernel module helpers.4 */5 6#include <linux/of.h>7#include <linux/module.h>8#include <linux/slab.h>9#include <linux/string.h>10 11ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)12{13	const char *compat;14	char *c;15	struct property *p;16	ssize_t csize;17	ssize_t tsize;18 19	/*20	 * Prevent a kernel oops in vsnprintf() -- it only allows passing a21	 * NULL ptr when the length is also 0. Also filter out the negative22	 * lengths...23	 */24	if ((len > 0 && !str) || len < 0)25		return -EINVAL;26 27	/* Name & Type */28	/* %p eats all alphanum characters, so %c must be used here */29	csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',30			 of_node_get_device_type(np));31	tsize = csize;32	if (csize >= len)33		csize = len > 0 ? len - 1 : 0;34	len -= csize;35	str += csize;36 37	of_property_for_each_string(np, "compatible", p, compat) {38		csize = strlen(compat) + 1;39		tsize += csize;40		if (csize >= len)41			continue;42 43		csize = snprintf(str, len, "C%s", compat);44		for (c = str; c; ) {45			c = strchr(c, ' ');46			if (c)47				*c++ = '_';48		}49		len -= csize;50		str += csize;51	}52 53	return tsize;54}55 56int of_request_module(const struct device_node *np)57{58	char *str;59	ssize_t size;60	int ret;61 62	if (!np)63		return -ENODEV;64 65	size = of_modalias(np, NULL, 0);66	if (size < 0)67		return size;68 69	/* Reserve an additional byte for the trailing '\0' */70	size++;71 72	str = kmalloc(size, GFP_KERNEL);73	if (!str)74		return -ENOMEM;75 76	of_modalias(np, str, size);77	str[size - 1] = '\0';78	ret = request_module(str);79	kfree(str);80 81	return ret;82}83EXPORT_SYMBOL_GPL(of_request_module);84