1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * arch/arm/boot/compressed/string.c 4 * 5 * Small subset of simple string routines 6 */ 7 8 #include <linux/string.h> 9 10 /* 11 * The decompressor is built without KASan but uses the same redirects as the 12 * rest of the kernel when CONFIG_KASAN is enabled, defining e.g. memcpy() 13 * to __memcpy() but since we are not linking with the main kernel string 14 * library in the decompressor, that will lead to link failures. 15 * 16 * Undefine KASan's versions, define the wrapped functions and alias them to 17 * the right names so that when e.g. __memcpy() appear in the code, it will 18 * still be linked to this local version of memcpy(). 19 */ 20 #ifdef CONFIG_KASAN 21 #undef memcpy 22 #undef memmove 23 #undef memset 24 void *__memcpy(void *__dest, __const void *__src, size_t __n) __alias(memcpy); 25 void *__memmove(void *__dest, __const void *__src, size_t count) __alias(memmove); 26 void *__memset(void *s, int c, size_t count) __alias(memset); 27 #endif 28 29 void *memcpy(void *__dest, __const void *__src, size_t __n) 30 { 31 int i = 0; 32 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; 33 34 for (i = __n >> 3; i > 0; i--) { 35 *d++ = *s++; 36 *d++ = *s++; 37 *d++ = *s++; 38 *d++ = *s++; 39 *d++ = *s++; 40 *d++ = *s++; 41 *d++ = *s++; 42 *d++ = *s++; 43 } 44 45 if (__n & 1 << 2) { 46 *d++ = *s++; 47 *d++ = *s++; 48 *d++ = *s++; 49 *d++ = *s++; 50 } 51 52 if (__n & 1 << 1) { 53 *d++ = *s++; 54 *d++ = *s++; 55 } 56 57 if (__n & 1) 58 *d++ = *s++; 59 60 return __dest; 61 } 62 63 void *memmove(void *__dest, __const void *__src, size_t count) 64 { 65 unsigned char *d = __dest; 66 const unsigned char *s = __src; 67 68 if (__dest == __src) 69 return __dest; 70 71 if (__dest < __src) 72 return memcpy(__dest, __src, count); 73 74 while (count--) 75 d[count] = s[count]; 76 return __dest; 77 } 78 79 size_t strlen(const char *s) 80 { 81 const char *sc = s; 82 83 while (*sc != '\0') 84 sc++; 85 return sc - s; 86 } 87 88 size_t strnlen(const char *s, size_t count) 89 { 90 const char *sc; 91 92 for (sc = s; count-- && *sc != '\0'; ++sc) 93 /* nothing */; 94 return sc - s; 95 } 96 97 int memcmp(const void *cs, const void *ct, size_t count) 98 { 99 const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count; 100 int res = 0; 101 102 while (su1 < end) { 103 res = *su1++ - *su2++; 104 if (res) 105 break; 106 } 107 return res; 108 } 109 110 int strcmp(const char *cs, const char *ct) 111 { 112 unsigned char c1, c2; 113 int res = 0; 114 115 do { 116 c1 = *cs++; 117 c2 = *ct++; 118 res = c1 - c2; 119 if (res) 120 break; 121 } while (c1); 122 return res; 123 } 124 125 void *memchr(const void *s, int c, size_t count) 126 { 127 const unsigned char *p = s; 128 129 while (count--) 130 if ((unsigned char)c == *p++) 131 return (void *)(p - 1); 132 return NULL; 133 } 134 135 char *strchr(const char *s, int c) 136 { 137 while (*s != (char)c) 138 if (*s++ == '\0') 139 return NULL; 140 return (char *)s; 141 } 142 143 char *strrchr(const char *s, int c) 144 { 145 const char *last = NULL; 146 do { 147 if (*s == (char)c) 148 last = s; 149 } while (*s++); 150 return (char *)last; 151 } 152 153 #undef memset 154 155 void *memset(void *s, int c, size_t count) 156 { 157 char *xs = s; 158 while (count--) 159 *xs++ = c; 160 return s; 161 } 162