mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	In of_modalias(), there's no dire need to call strlen() (and then add 1 to its result to account for the 'C' char preceding the compat string). Replace that strlen() with snprintf() (currently below it) -- this way, we always try to print the compat string but then only advance the str and len parameters iff the compat string fit into the remaining buffer space... Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru> Link: https://lore.kernel.org/r/471418be-5d2f-4d14-bd9e-9e8f0526241f@omp.ru Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
		
			
				
	
	
		
			81 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/*
 | 
						|
 * Linux kernel module helpers.
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/of.h>
 | 
						|
#include <linux/module.h>
 | 
						|
#include <linux/slab.h>
 | 
						|
#include <linux/string.h>
 | 
						|
 | 
						|
ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
 | 
						|
{
 | 
						|
	const char *compat;
 | 
						|
	char *c;
 | 
						|
	struct property *p;
 | 
						|
	ssize_t csize;
 | 
						|
	ssize_t tsize;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Prevent a kernel oops in vsnprintf() -- it only allows passing a
 | 
						|
	 * NULL ptr when the length is also 0. Also filter out the negative
 | 
						|
	 * lengths...
 | 
						|
	 */
 | 
						|
	if ((len > 0 && !str) || len < 0)
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	/* Name & Type */
 | 
						|
	/* %p eats all alphanum characters, so %c must be used here */
 | 
						|
	csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
 | 
						|
			 of_node_get_device_type(np));
 | 
						|
	tsize = csize;
 | 
						|
	if (csize >= len)
 | 
						|
		csize = len > 0 ? len - 1 : 0;
 | 
						|
	len -= csize;
 | 
						|
	str += csize;
 | 
						|
 | 
						|
	of_property_for_each_string(np, "compatible", p, compat) {
 | 
						|
		csize = snprintf(str, len, "C%s", compat);
 | 
						|
		tsize += csize;
 | 
						|
		if (csize >= len)
 | 
						|
			continue;
 | 
						|
		for (c = str; c; ) {
 | 
						|
			c = strchr(c, ' ');
 | 
						|
			if (c)
 | 
						|
				*c++ = '_';
 | 
						|
		}
 | 
						|
		len -= csize;
 | 
						|
		str += csize;
 | 
						|
	}
 | 
						|
 | 
						|
	return tsize;
 | 
						|
}
 | 
						|
 | 
						|
int of_request_module(const struct device_node *np)
 | 
						|
{
 | 
						|
	char *str;
 | 
						|
	ssize_t size;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (!np)
 | 
						|
		return -ENODEV;
 | 
						|
 | 
						|
	size = of_modalias(np, NULL, 0);
 | 
						|
	if (size < 0)
 | 
						|
		return size;
 | 
						|
 | 
						|
	/* Reserve an additional byte for the trailing '\0' */
 | 
						|
	size++;
 | 
						|
 | 
						|
	str = kmalloc(size, GFP_KERNEL);
 | 
						|
	if (!str)
 | 
						|
		return -ENOMEM;
 | 
						|
 | 
						|
	of_modalias(np, str, size);
 | 
						|
	str[size - 1] = '\0';
 | 
						|
	ret = request_module(str);
 | 
						|
	kfree(str);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(of_request_module);
 |