#define DEFINE_STRCPY(type, name) \
type *name(type * restrict dest, const type * restrict src) { \
- assert(dest); \
- type *ret = dest; \
+ type *ret = ASSERT_PTR(dest); \
\
if (!src) { \
*dest = '\0'; \
p++;
if (*p == '\0')
return false;
- match |= *p == *h;
+ if (*p == *h)
+ match = true;
can_range = true;
continue;
}
return efi_fnmatch_internal(pattern, haystack, 32);
}
+#define DEFINE_PARSE_NUMBER(type, name) \
+ bool name(const type *s, uint64_t *ret_u, const type **ret_tail) { \
+ assert(ret_u); \
+ \
+ if (!s) \
+ return false; \
+ \
+ /* Need at least one digit. */ \
+ if (*s < '0' || *s > '9') \
+ return false; \
+ \
+ uint64_t u = 0; \
+ while (*s >= '0' && *s <= '9') { \
+ if (__builtin_mul_overflow(u, 10, &u)) \
+ return false; \
+ if (__builtin_add_overflow(u, *s - '0', &u)) \
+ return false; \
+ s++; \
+ } \
+ \
+ if (!ret_tail && *s != '\0') \
+ return false; \
+ \
+ *ret_u = u; \
+ if (ret_tail) \
+ *ret_tail = s; \
+ return true; \
+ }
+
+DEFINE_PARSE_NUMBER(char, parse_number8);
+DEFINE_PARSE_NUMBER(char16_t, parse_number16);
+
int efi_memcmp(const void *p1, const void *p2, size_t n) {
const uint8_t *up1 = p1, *up2 = p2;
int r;
if (!dest || !src || n == 0)
return dest;
+#ifdef SD_BOOT
+ /* The firmware-provided memcpy is likely optimized, so use that. The function is guaranteed to be
+ * available by the UEFI spec. We still make it depend on the boot services pointer being set just in
+ * case the compiler emits a call before it is available. */
+ if (_likely_(BS)) {
+ BS->CopyMem(dest, (void *) src, n);
+ return dest;
+ }
+#endif
+
uint8_t *d = dest;
const uint8_t *s = src;
if (!p || n == 0)
return p;
+#ifdef SD_BOOT
+ /* See comment in efi_memcpy. Note that the signature has c and n swapped! */
+ if (_likely_(BS)) {
+ BS->SetMem(p, n, c);
+ return p;
+ }
+#endif
+
uint8_t *q = p;
while (n > 0) {
*q = c;
# undef memcmp
# undef memcpy
# undef memset
-/* Provide the actual implementation for the builtins. To prevent a linker error, we mark memcpy/memset as
- * weak, because gnu-efi is currently providing them. */
-__attribute__((alias("efi_memcmp"))) int memcmp(const void *p1, const void *p2, size_t n);
-__attribute__((weak, alias("efi_memcpy"))) void *memcpy(void * restrict dest, const void * restrict src, size_t n);
-__attribute__((weak, alias("efi_memset"))) void *memset(void *p, int c, size_t n);
+/* Provide the actual implementation for the builtins by providing aliases. These need to be marked as used,
+ * as otherwise the compiler might remove them but still emit calls, which would break when linking.
+ * To prevent a different linker error, we mark memcpy/memset as weak, because gnu-efi is currently
+ * providing them. */
+__attribute__((used, alias("efi_memcmp"))) int memcmp(const void *p1, const void *p2, size_t n);
+__attribute__((used, weak, alias("efi_memcpy"))) void *memcpy(void * restrict dest, const void * restrict src, size_t n);
+__attribute__((used, weak, alias("efi_memset"))) void *memset(void *p, int c, size_t n);
#endif