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:
Casey Connolly
2026-04-21 11:19:49 -06:00
committed by Tom Rini
parent f5e96fdffc
commit 139f5292e7
4 changed files with 65 additions and 0 deletions
+19
View File
@@ -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 */
+13
View File
@@ -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);
+2
View File
@@ -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 *);
+31
View File
@@ -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