string: add strdup_const and kstrdup_const
Extend Linux compat by adding kstrdup_const(), backed by lib/string.c. This leverages U-Boots .rodata section on ARM64 to avoid pointlessly duplicating const strings. This is used by the Linux CCF_FULL port and may be useful elsewhere in U-Boot. Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#define _ASM_GENERIC_SECTIONS_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* References to section boundaries */
|
||||
|
||||
@@ -62,6 +63,24 @@ static inline int arch_is_kernel_data(unsigned long addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* is_kernel_rodata - checks if the pointer address is located in the
|
||||
* .rodata section
|
||||
*
|
||||
* @addr: address to check
|
||||
*
|
||||
* Returns: true if the address is located in .rodata, false otherwise.
|
||||
*/
|
||||
static inline bool is_kernel_rodata(unsigned long addr)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
return addr >= (unsigned long)__start_rodata &&
|
||||
addr < (unsigned long)__end_rodata;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* U-Boot-specific things begin here */
|
||||
|
||||
/* Start of U-Boot text region */
|
||||
|
||||
@@ -67,6 +67,19 @@ static inline void vfree(const void *addr)
|
||||
free((void *)addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* kstrdup_const - conditionally duplicate an existing const string
|
||||
* @s: the string to duplicate
|
||||
* @gfp: the GFP mask used in the kmalloc() call when allocating memory
|
||||
*
|
||||
* Note: Strings allocated by kstrdup_const should be freed by kfree_const and
|
||||
* must not be passed to krealloc().
|
||||
*
|
||||
* Return: source string if it is in .rodata section otherwise
|
||||
* fallback to kstrdup.
|
||||
*/
|
||||
#define kstrdup_const(s, gfp) strdup_const(s)
|
||||
|
||||
struct kmem_cache { int sz; };
|
||||
|
||||
struct kmem_cache *get_mem(int element_sz);
|
||||
|
||||
@@ -104,6 +104,8 @@ size_t strcspn(const char *s, const char *reject);
|
||||
#ifndef __HAVE_ARCH_STRDUP
|
||||
extern char * strdup(const char *);
|
||||
extern char * strndup(const char *, size_t);
|
||||
extern const char *strdup_const(const char *s);
|
||||
extern void kfree_const(const void *x);
|
||||
#endif
|
||||
#ifndef __HAVE_ARCH_STRSWAB
|
||||
extern char * strswab(const char *);
|
||||
|
||||
@@ -379,6 +379,37 @@ char * strndup(const char *s, size_t n)
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* strdup_const - conditionally duplicate an existing const string
|
||||
* @s: the string to duplicate
|
||||
*
|
||||
* Note: Strings allocated by kstrdup_const should be freed by kfree_const and
|
||||
* must not be passed to krealloc().
|
||||
*
|
||||
* Return: source string if it is in .rodata section otherwise
|
||||
* fallback to kstrdup.
|
||||
*/
|
||||
const char *strdup_const(const char *s)
|
||||
{
|
||||
if (is_kernel_rodata((unsigned long)s))
|
||||
return s;
|
||||
|
||||
return strdup(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* kfree_const - conditionally free memory
|
||||
* @x: pointer to the memory
|
||||
*
|
||||
* Function calls kfree only if @x is not in .rodata section.
|
||||
*/
|
||||
void kfree_const(const void *x)
|
||||
{
|
||||
if (!is_kernel_rodata((unsigned long)x))
|
||||
free((void *)x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __HAVE_ARCH_STRSPN
|
||||
|
||||
Reference in New Issue
Block a user