soc/amd/common/psp/psp_def.h: increase P2C_BUFFER_MAXSIZE
[coreboot2.git] / payloads / libpayload / libc / memory.c
blobfff295e54c51db19577e8ddd9f02f8feb9e880fe
1 /*
3 * It has originally been taken from the HelenOS project
4 * (http://www.helenos.eu), and slightly modified for our purposes.
6 * Copyright (c) 2005 Martin Decky
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * - The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <libpayload.h>
35 static void *default_memset(void *const s, const int c, size_t n)
37 size_t i;
38 u8 *dst = s;
39 unsigned long w = c & 0xff;
41 const u8 *const aligned_start =
42 (const u8 *)ALIGN_UP((uintptr_t)dst, sizeof(unsigned long));
43 for (; n > 0 && dst != aligned_start; --n, ++dst)
44 *dst = (u8)c;
46 for (i = 1; i < sizeof(unsigned long); i <<= 1)
47 w = (w << (i * 8)) | w;
49 for (i = 0; i < n / sizeof(unsigned long); i++)
50 ((unsigned long *)dst)[i] = w;
52 dst += i * sizeof(unsigned long);
54 for (i = 0; i < n % sizeof(unsigned long); i++)
55 dst[i] = (u8)c;
57 return s;
60 void *memset(void *s, int c, size_t n)
61 __attribute__((weak, alias("default_memset")));
63 static void *default_memcpy(void *dst, const void *src, size_t n)
65 size_t i;
66 void *ret = dst;
68 if (IS_ALIGNED((uintptr_t)dst, sizeof(unsigned long)) &&
69 IS_ALIGNED((uintptr_t)src, sizeof(unsigned long))) {
70 for (i = 0; i < n / sizeof(unsigned long); i++)
71 ((unsigned long *)dst)[i] = ((unsigned long *)src)[i];
73 src += i * sizeof(unsigned long);
74 dst += i * sizeof(unsigned long);
75 n -= i * sizeof(unsigned long);
78 for (i = 0; i < n; i++)
79 ((u8 *)dst)[i] = ((u8 *)src)[i];
81 return ret;
84 void *memcpy(void *dst, const void *src, size_t n)
85 __attribute__((weak, alias("default_memcpy")));
87 static void *default_memmove(void *dst, const void *src, size_t n)
89 size_t offs;
90 ssize_t i;
92 if (src > dst)
93 return default_memcpy(dst, src, n);
95 if (!IS_ALIGNED((uintptr_t)dst, sizeof(unsigned long)) ||
96 !IS_ALIGNED((uintptr_t)src, sizeof(unsigned long))) {
97 for (i = n - 1; i >= 0; i--)
98 ((u8 *)dst)[i] = ((u8 *)src)[i];
99 return dst;
102 offs = n - (n % sizeof(unsigned long));
104 for (i = (n % sizeof(unsigned long)) - 1; i >= 0; i--)
105 ((u8 *)dst)[i + offs] = ((u8 *)src)[i + offs];
107 for (i = n / sizeof(unsigned long) - 1; i >= 0; i--)
108 ((unsigned long *)dst)[i] = ((unsigned long *)src)[i];
110 return dst;
113 void *memmove(void *dst, const void *src, size_t n)
114 __attribute__((weak, alias("default_memmove")));
117 * Compare two memory areas.
119 * @param s1 Pointer to the first area to compare.
120 * @param s2 Pointer to the second area to compare.
121 * @param n Size of the first area in bytes (both must have the same length).
122 * @return If n is 0, return zero. Otherwise, return a value less than, equal
123 * to, or greater than zero if s1 is found less than, equal to, or
124 * greater than s2 respectively.
127 static int default_memcmp(const void *s1, const void *s2, size_t n)
129 size_t i = 0;
130 const unsigned long *w1 = s1, *w2 = s2;
132 if (IS_ALIGNED((uintptr_t)s1, sizeof(unsigned long)) &&
133 IS_ALIGNED((uintptr_t)s2, sizeof(unsigned long)))
134 for (; i < n / sizeof(unsigned long); i++)
135 if (w1[i] != w2[i])
136 break; /* fall through to find differing byte */
138 for (i *= sizeof(unsigned long); i < n; i++)
139 if (((u8 *)s1)[i] != ((u8 *)s2)[i])
140 return ((u8 *)s1)[i] - ((u8 *)s2)[i];
142 return 0;
145 int memcmp(const void *s1, const void *s2, size_t n)
146 __attribute__((weak, alias("default_memcmp")));
148 void *memchr(const void *s, int c, size_t n)
150 unsigned char *p = (unsigned char *)s;
151 while (n--)
152 if (*p != (unsigned char)c)
153 p++;
154 else
155 return p;
156 return 0;