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