* Re: [RFC PATCH 1/1] MdePkg: Add a libc implementation
2023-03-31 2:30 [RFC PATCH 1/1] MdePkg: Add a libc implementation Pedro Falcato
2023-03-31 11:55 ` [edk2-devel] " Gerd Hoffmann
@ 2023-04-06 3:07 ` Michael D Kinney
1 sibling, 0 replies; 3+ messages in thread
From: Michael D Kinney @ 2023-04-06 3:07 UTC (permalink / raw)
To: Pedro Falcato, devel@edk2.groups.io
Cc: Gao, Liming, Liu, Zhiguang, Lin, Benny, Kinney, Michael D
Hi Pedro,
Thank you for starting this.
I recall some challenges with the Openssl libc wrapper, so let's work on that one last.
If we can get a libc wrapper that is compatible with Brotli, regular expression,
jannson, and fdtlib that would be a huge step forward.
Can you test your code against these 3 use cases that are already in edk2?
* MdeModulePkg\Library\BrotliCustomDecompressLib
* MdeModulePkg\Universal\RegularExpressionDxe
* RedfishPkg\PrivateInclude\Crt
Mike
> -----Original Message-----
> From: Pedro Falcato <pedro.falcato@gmail.com>
> Sent: Thursday, March 30, 2023 7:31 PM
> To: devel@edk2.groups.io
> Cc: Pedro Falcato <pedro.falcato@gmail.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Liu, Zhiguang <zhiguang.liu@intel.com>; Lin, Benny <benny.lin@intel.com>
> Subject: [RFC PATCH 1/1] MdePkg: Add a libc implementation
>
> Add LibcLib, a libc implementation meant to centralize all libc bits in
> edk2.
>
> Work in progress, does not support Windows targets (CLANGPDB and MSVC)
> just yet.
>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
> Cc: Benny Lin <benny.lin@intel.com>
> Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com>
> ---
> Wrote this to fulfill the new needs for BaseFdtLib and libfdt.
> It's very much a work in progress. Please test (I have no way to test this,
> and I have not attempted to replace OpenSSL stuff just yet). It's not perfect,
> but I attempted to be as correct as possible. Please, comment.
>
> Some details:
> 1) I attempted to be as standards-correct as possible, used __name and _Name to avoid namespace polution.
> I (unfortunately) had to include Base.h for NULL, because defining my own would possibly spell disaster
> if someone included a C standard header and Base.h.
> 2) ProcessorBind.h implicitly polutes the global namespace. I don't think this is fixable.
> 3) In some places, I wrote my own functions when I could redirect to BaseMemoryLib stuff.
> The amount of possible points of failure made me nervous (max string size PCD, etc). To be discussed.
> 4) This should fulfill BaseFdtLib's needs. I went a bit more in-depth where I could (without wasting too much time).
> Of course, this means it's still missing a *HUGE* chunk of libc. I don't think I'm aiming to write a full libc here
> (haha).
> Just the common bits that may be useful for edk2.
> 5) As discussed before (in the context of compiler intrinsics), GCC and clang require memcpy, memset, and some others for
> valid
> codegen. This should possibly be done implicitly by BaseTools.
> 6) Again, please, comment or contribute. If anyone wants to send PRs or checkout directly, feel free:
> https://github.com/heatd/edk2/tree/wip-libc
>
> MdePkg/Include/limits.h | 69 ++++++++++++++
> MdePkg/Include/stdbool.h | 17 ++++
> MdePkg/Include/stddef.h | 26 +++++
> MdePkg/Include/stdint.h | 116 +++++++++++++++++++++++
> MdePkg/Include/stdlib.h | 21 ++++
> MdePkg/Include/string.h | 86 +++++++++++++++++
> MdePkg/Include/types.h | 27 ++++++
> MdePkg/Library/LibcLib/LibcLib.inf | 38 ++++++++
> MdePkg/Library/LibcLib/Stdlib/strtoul.c | 121 ++++++++++++++++++++++++
> MdePkg/Library/LibcLib/String/memchr.c | 19 ++++
> MdePkg/Library/LibcLib/String/memcmp.c | 19 ++++
> MdePkg/Library/LibcLib/String/memcpy.c | 29 ++++++
> MdePkg/Library/LibcLib/String/memset.c | 21 ++++
> MdePkg/Library/LibcLib/String/strchr.c | 56 +++++++++++
> MdePkg/Library/LibcLib/String/strcmp.c | 27 ++++++
> MdePkg/Library/LibcLib/String/strcpy.c | 59 ++++++++++++
> MdePkg/Library/LibcLib/String/strlen.c | 16 ++++
> MdePkg/MdeLibs.dsc.inc | 1 +
> MdePkg/MdePkg.dec | 4 +
> MdePkg/MdePkg.dsc | 1 +
> 20 files changed, 773 insertions(+)
> create mode 100644 MdePkg/Include/limits.h
> create mode 100644 MdePkg/Include/stdbool.h
> create mode 100644 MdePkg/Include/stddef.h
> create mode 100644 MdePkg/Include/stdint.h
> create mode 100644 MdePkg/Include/stdlib.h
> create mode 100644 MdePkg/Include/string.h
> create mode 100644 MdePkg/Include/types.h
> create mode 100644 MdePkg/Library/LibcLib/LibcLib.inf
> create mode 100644 MdePkg/Library/LibcLib/Stdlib/strtoul.c
> create mode 100644 MdePkg/Library/LibcLib/String/memchr.c
> create mode 100644 MdePkg/Library/LibcLib/String/memcmp.c
> create mode 100644 MdePkg/Library/LibcLib/String/memcpy.c
> create mode 100644 MdePkg/Library/LibcLib/String/memset.c
> create mode 100644 MdePkg/Library/LibcLib/String/strchr.c
> create mode 100644 MdePkg/Library/LibcLib/String/strcmp.c
> create mode 100644 MdePkg/Library/LibcLib/String/strcpy.c
> create mode 100644 MdePkg/Library/LibcLib/String/strlen.c
>
> diff --git a/MdePkg/Include/limits.h b/MdePkg/Include/limits.h
> new file mode 100644
> index 000000000000..f87b870e6cbc
> --- /dev/null
> +++ b/MdePkg/Include/limits.h
> @@ -0,0 +1,69 @@
> +/** @file
> + ISO C limits.h
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _LIMITS_H
> +#define _LIMITS_H
> +
> +#if defined (MDE_CPU_X64) || defined (MDE_CPU_AARCH64)
> +// Hint for LONG_* stuff
> +#define __LIMITS_64BIT
> +#endif
> +
> +#ifndef __GNUC__
> +// TODO: MSVC support is missing (some types are not exactly the same)
> +// Should this whole logic be in ProcessorBind.h or something?
> + #error "MSVC support TODO"
> +#endif
> +
> +#define CHAR_BIT 8
> +
> +/* Char limits - for char, signed char, unsigned char */
> +#define SCHAR_MIN -128
> +#define SCHAR_MAX 127
> +#define UCHAR_MAX 255
> +
> +// Note: We must check if chars are signed or unsigned here. 0xff = -128 for signed chars
> +#if '\xff' < 0
> +#define __CHAR_IS_SIGNED
> +#endif
> +
> +#ifdef __CHAR_IS_SIGNED
> +#define CHAR_MIN SCHAR_MIN
> +#define CHAR_MAX SCHAR_MAX
> +#else
> +#define CHAR_MIN 0
> +#define CHAR_MAX UCHAR_MAX
> +#endif
> +
> +/* Short limits - for short, unsigned short */
> +#define SHRT_MIN (-1 - 0x7fff)
> +#define SHRT_MAX 0x7fff
> +#define USHRT_MAX 0xffff
> +
> +/* Int limits - for int, unsigned int */
> +#define INT_MIN (-1 - 0x7fffffff)
> +#define INT_MAX 0x7fffffff
> +#define UINT_MAX 0xffffffffU
> +
> +/* Long limits - for long, unsigned long and long long variants */
> +
> +#ifdef __LIMITS_64BIT
> +#define LONG_MAX 0x7fffffffffffffffL
> +#define LONG_MIN (-1 - 0x7fffffffffffffffL)
> +#define ULONG_MAX 0xffffffffffffffffUL
> +#else
> +#define LONG_MAX 0x7fffffffL
> +#define LONG_MIN (-1 - 0x7fffffffL)
> +#define ULONG_MAX 0xffffffffUL
> +#endif
> +
> +/* long long must always be 64-bit for EFI UINT64 */
> +#define LLONG_MIN (-1 - 0x7fffffffffffffffLL)
> +#define LLONG_MAX 0x7fffffffffffffffLL
> +#define ULLONG_MAX 0xffffffffffffffffULL
> +
> +#endif
> diff --git a/MdePkg/Include/stdbool.h b/MdePkg/Include/stdbool.h
> new file mode 100644
> index 000000000000..c365fbcc4f0f
> --- /dev/null
> +++ b/MdePkg/Include/stdbool.h
> @@ -0,0 +1,17 @@
> +/** @file
> + ISO C stdbool.h
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _STDBOOL_H
> +#define _STDBOOL_H
> +
> +#define bool _Bool
> +#define true 1
> +#define false 0
> +
> +#define __bool_true_false_are_defined 1
> +
> +#endif
> diff --git a/MdePkg/Include/stddef.h b/MdePkg/Include/stddef.h
> new file mode 100644
> index 000000000000..86c17102f4b2
> --- /dev/null
> +++ b/MdePkg/Include/stddef.h
> @@ -0,0 +1,26 @@
> +/** @file
> + ISO C stddef.h
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _STDDEF_H
> +#define _STDDEF_H
> +
> +#include <Base.h> // For NULL
> +// TODO: Namespace polution
> +
> +typedef INTN ptrdiff_t;
> +typedef UINTN size_t;
> +typedef CHAR16 wchar_t;
> +
> +// offsetof taken from Base.h
> +
> +#if (defined (__GNUC__) && __GNUC__ >= 4) || defined (__clang__)
> +#define offsetof(TYPE, Field) ((UINTN) __builtin_offsetof(TYPE, Field))
> +#else
> +#define offsetof(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
> +#endif
> +
> +#endif
> diff --git a/MdePkg/Include/stdint.h b/MdePkg/Include/stdint.h
> new file mode 100644
> index 000000000000..ed554ff1773d
> --- /dev/null
> +++ b/MdePkg/Include/stdint.h
> @@ -0,0 +1,116 @@
> +/** @file
> + ISO C stdint.h
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _STDINT_H
> +#define _STDINT_H
> +
> +// INT(N), UINT(N) taken from ProcessorBind.h
> +typedef INT8 int8_t;
> +typedef INT16 int16_t;
> +typedef INT32 int32_t;
> +typedef INT64 int64_t;
> +
> +typedef UINT8 uint8_t;
> +typedef UINT16 uint16_t;
> +typedef UINT32 uint32_t;
> +typedef UINT64 uint64_t;
> +
> +typedef int8_t int_least8_t;
> +typedef int16_t int_least16_t;
> +typedef int32_t int_least32_t;
> +typedef int64_t int_least64_t;
> +
> +typedef uint8_t uint_least8_t;
> +typedef uint16_t uint_least16_t;
> +typedef uint32_t uint_least32_t;
> +typedef uint64_t uint_least64_t;
> +
> +typedef int8_t int_fast8_t;
> +typedef int16_t int_fast16_t;
> +typedef int32_t int_fast32_t;
> +typedef int64_t int_fast64_t;
> +
> +typedef uint8_t uint_fast8_t;
> +typedef uint16_t uint_fast16_t;
> +typedef uint32_t uint_fast32_t;
> +typedef uint64_t uint_fast64_t;
> +
> +typedef INTN intptr_t;
> +typedef UINTN uintptr_t;
> +
> +typedef INT64 intmax_t;
> +typedef UINT64 uintmax_t;
> +
> +/* Limits for the types declared above */
> +#define INT8_MIN -128
> +#define INT8_MAX 127
> +#define UINT8_MAX 255
> +#define INT16_MIN (-1 - 0x7fff)
> +#define INT16_MAX 0x7fff
> +#define UINT16_MAX 0xffff
> +#define INT32_MIN (-1 - 0x7fffffff)
> +#define INT32_MAX 0x7fffffff
> +#define UINT32_MAX 0xffffffffU
> +#define INT64_MIN (-1 - 0x7fffffffffffffffLL)
> +#define INT64_MAX 0x7fffffffffffffffLL
> +#define UINT64_MAX 0xffffffffffffffffULL
> +
> +#define INT_LEAST8_MIN INT8_MIN
> +#define INT_LEAST8_MAX INT8_MAX
> +#define UINT_LEAST8_MAX UINT8_MAX
> +#define INT_LEAST16_MIN INT16_MIN
> +#define INT_LEAST16_MAX INT16_MAX
> +#define UINT_LEAST16_MAX UINT16_MAX
> +#define INT_LEAST32_MIN INT32_MIN
> +#define INT_LEAST32_MAX INT32_MAX
> +#define UINT_LEAST32_MAX UINT32_MAX
> +#define INT_LEAST64_MIN INT64_MIN
> +#define INT_LEAST64_MAX INT64_MAX
> +#define UINT_LEAST64_MAX UINT64_MAX
> +
> +#define INT_FAST8_MIN INT8_MIN
> +#define INT_FAST8_MAX INT8_MAX
> +#define UINT_FAST8_MAX UINT8_MAX
> +#define INT_FAST16_MIN INT16_MIN
> +#define INT_FAST16_MAX INT16_MAX
> +#define UINT_FAST16_MAX UINT16_MAX
> +#define INT_FAST32_MIN INT32_MIN
> +#define INT_FAST32_MAX INT32_MAX
> +#define UINT_FAST32_MAX UINT32_MAX
> +#define INT_FAST64_MIN INT64_MIN
> +#define INT_FAST64_MAX INT64_MAX
> +#define UINT_FAST64_MAX UINT64_MAX
> +
> +#define INTPTR_MIN (1 - MAX_INTN)
> +#define INTPTR_MAX MAX_INTN
> +#define UINTPTR_MAX MAX_UINTN
> +
> +#define INTMAX_MIN INT64_MIN
> +#define INTMAX_MAX INT64_MAX
> +#define UINTMAX_MAX UINT64_MAX
> +
> +#define PTRDIFF_MIN INTPTR_MIN
> +#define PTRDIFF_MAX INTPTR_MAX
> +#define SIZE_MAX MAX_UINTN
> +
> +// TODO: SIG_ATOMIC, WCHAR, WINT
> +
> +/* Macros to declare (u)int(N)_t constants */
> +
> +#define INT8_C(c) c
> +#define INT16_C(c) c
> +#define INT32_C(c) c
> +#define INT64_C(c) c ## LL
> +#define UINT8_C(c) c
> +#define UINT16_C(c) c
> +#define UINT32_C(c) c ## U
> +#define UINT64_C(c) c ## ULL
> +
> +#define INTMAX_C(c) c ## LL
> +#define UINTMAX_C(c) c ## ULL
> +
> +#endif
> diff --git a/MdePkg/Include/stdlib.h b/MdePkg/Include/stdlib.h
> new file mode 100644
> index 000000000000..954da4bbea8e
> --- /dev/null
> +++ b/MdePkg/Include/stdlib.h
> @@ -0,0 +1,21 @@
> +/** @file
> + ISO C stdlib.h
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _STDLIB_H
> +#define _STDLIB_H
> +
> +#define __NEED_NULL
> +#include <types.h>
> +
> +unsigned long
> +strtoul (
> + const char *Nptr,
> + char **EndPtr,
> + int Base
> + );
> +
> +#endif
> diff --git a/MdePkg/Include/string.h b/MdePkg/Include/string.h
> new file mode 100644
> index 000000000000..31d95db91cfe
> --- /dev/null
> +++ b/MdePkg/Include/string.h
> @@ -0,0 +1,86 @@
> +/** @file
> + ISO C string.h
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _STRING_H
> +#define _STRING_H
> +
> +#define __NEED_size_t
> +#define __NEED_NULL
> +#include <types.h>
> +
> +void *
> +memcpy (
> + void *restrict Dst,
> + const void *restrict Src,
> + size_t Count
> + );
> +
> +void *
> +memmove (
> + void *Dst,
> + const void *Src,
> + size_t Count
> + );
> +
> +void *
> +memset (
> + void *Buf,
> + int Val,
> + size_t Count
> + );
> +
> +void *
> +memchr (
> + const void *Buf,
> + int Char,
> + size_t Count
> + );
> +
> +int
> +memcmp (
> + const void *S1,
> + const void *S2,
> + size_t Count
> + );
> +
> +size_t
> +strlen (
> + const char *Str
> + );
> +
> +char *
> +strcpy (
> + char *restrict Dest,
> + const char *restrict Source
> + );
> +
> +char *
> +strncpy (
> + char *restrict Dest,
> + const char *restrict Source,
> + size_t Count
> + );
> +
> +char *
> +strcat (
> + char *restrict Dest,
> + const char *restrict Source
> + );
> +
> +char *
> +strchr (
> + const char *Str,
> + int Char
> + );
> +
> +char *
> +strrchr (
> + const char *Str,
> + int Char
> + );
> +
> +#endif
> diff --git a/MdePkg/Include/types.h b/MdePkg/Include/types.h
> new file mode 100644
> index 000000000000..97e90d7b31e3
> --- /dev/null
> +++ b/MdePkg/Include/types.h
> @@ -0,0 +1,27 @@
> +/** @file
> + ISO C auxiliary types file
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _TYPES_H
> +#define _TYPES_H
> +
> +/* C has a variety of types we must define in a lot of header files, without
> + including the "canonical" header file due to namespace pollution reasons.
> + So define them here and use __NEED_ macros to ask for certain definitions.
> + */
> +
> +#if defined (__NEED_size_t) && !defined (__defined_size_t)
> +typedef UINTN size_t;
> +#define __defined_size_t
> +#endif
> +
> +#if defined (__NEED_NULL) && !defined (__defined_NULL)
> + #include <Base.h>
> +#define __defined_NULL
> +// TODO: Namespace pollution
> +#endif
> +
> +#endif
> diff --git a/MdePkg/Library/LibcLib/LibcLib.inf b/MdePkg/Library/LibcLib/LibcLib.inf
> new file mode 100644
> index 000000000000..d15def794973
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/LibcLib.inf
> @@ -0,0 +1,38 @@
> +## @file
> +# ISO C libc implementation for EDK2 modules
> +#
> +# Copyright (c) 2023 Pedro Falcato All rights reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> + INF_VERSION = 0x0001001B
> + BASE_NAME = LibcLib
> + FILE_GUID = 469201d7-0884-497a-ba93-ec5ee911b0e8
> + MODULE_TYPE = BASE
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = LibcLib|BASE
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 AARCH64
> +#
> +
> +[Sources]
> + String/strcpy.c
> + String/strcmp.c
> + String/strlen.c
> + String/strchr.c
> + String/memcpy.c
> + String/memset.c
> + String/memchr.c
> + String/memcmp.c
> + Stdlib/strtoul.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + BaseMemoryLib
> diff --git a/MdePkg/Library/LibcLib/Stdlib/strtoul.c b/MdePkg/Library/LibcLib/Stdlib/strtoul.c
> new file mode 100644
> index 000000000000..952d3b899c5e
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/Stdlib/strtoul.c
> @@ -0,0 +1,121 @@
> +/** @file
> + memcpy-like functions
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <stdlib.h>
> +#include <limits.h>
> +
> +STATIC
> +int
> +__isspace (
> + int ch
> + )
> +{
> + // basic ASCII ctype.h:isspace(). Not efficient
> + return ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f';
> +}
> +
> +unsigned long
> +strtoul (
> + const char *Nptr,
> + char **EndPtr,
> + int Base
> + )
> +{
> + BOOLEAN Negate;
> + BOOLEAN Overflow;
> + unsigned long Val;
> +
> + Negate = FALSE;
> + Overflow = FALSE;
> + Val = 0;
> +
> + // Reject bad numeric bases
> + if ((Base < 0) || (Base == 1) || (Base > 36)) {
> + return 0;
> + }
> +
> + // Skip whitespace
> + while (__isspace (*Nptr)) {
> + Nptr++;
> + }
> +
> + // Check for + or - prefixes
> + if (*Nptr == '-') {
> + Negate = TRUE;
> + Nptr++;
> + } else if (*Nptr == '+') {
> + Nptr++;
> + }
> +
> + // Consume the start, autodetecting base if needed
> + if ((Nptr[0] == '0') && ((Nptr[1] == 'x') || (Nptr[1] == 'X')) && ((Base == 0) || (Base == 16))) {
> + // Hex
> + Nptr += 2;
> + Base = 16;
> + } else if ((Nptr[0] == '0') && ((Nptr[1] == 'b') || (Nptr[1] == 'B')) && ((Base == 0) || (Base == 2))) {
> + // Binary (standard pending C23)
> + Nptr += 2;
> + Base = 2;
> + } else if ((Nptr[0] == '0') && ((Base == 0) || (Base == 8))) {
> + // Octal
> + Nptr++;
> + Base = 8;
> + } else {
> + if (Base == 0) {
> + // Assume decimal
> + Base = 10;
> + }
> + }
> +
> + while (TRUE) {
> + int Digit;
> + char C;
> + unsigned long NewVal;
> +
> + C = *Nptr;
> + Digit = -1;
> +
> + if ((C >= '0') && (C <= '9')) {
> + Digit = C - '0';
> + } else if ((C >= 'a') && (C <= 'z')) {
> + Digit = C - 'a' + 10;
> + } else if ((C >= 'A') && (C <= 'Z')) {
> + Digit = C - 'A' + 10;
> + }
> +
> + if ((Digit == -1) || (Digit >= Base)) {
> + // Note that this case also handles the \0
> + if (EndPtr) {
> + *EndPtr = (char *)Nptr;
> + }
> +
> + break;
> + }
> +
> + NewVal = Val * Base + Digit;
> +
> + if (NewVal < Val) {
> + // Overflow
> + Overflow = TRUE;
> + }
> +
> + Val = NewVal;
> +
> + Nptr++;
> + }
> +
> + if (Negate) {
> + Val = -Val;
> + }
> +
> + if (Overflow) {
> + Val = ULONG_MAX;
> + }
> +
> + // TODO: We're lacking errno here.
> + return Val;
> +}
> diff --git a/MdePkg/Library/LibcLib/String/memchr.c b/MdePkg/Library/LibcLib/String/memchr.c
> new file mode 100644
> index 000000000000..cea8b71349f0
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/memchr.c
> @@ -0,0 +1,19 @@
> +/** @file
> + memchr-like functions
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <string.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +void *
> +memchr (
> + const void *Buf,
> + int Char,
> + size_t Count
> + )
> +{
> + return ScanMem8 (Buf, Count, Char);
> +}
> diff --git a/MdePkg/Library/LibcLib/String/memcmp.c b/MdePkg/Library/LibcLib/String/memcmp.c
> new file mode 100644
> index 000000000000..d02aa5d980f7
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/memcmp.c
> @@ -0,0 +1,19 @@
> +/** @file
> + memcmp-like functions
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <string.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +int
> +memcmp (
> + const void *S1,
> + const void *S2,
> + size_t Count
> + )
> +{
> + return (int)CompareMem (S1, S2, Count);
> +}
> diff --git a/MdePkg/Library/LibcLib/String/memcpy.c b/MdePkg/Library/LibcLib/String/memcpy.c
> new file mode 100644
> index 000000000000..d6e85f7eb37f
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/memcpy.c
> @@ -0,0 +1,29 @@
> +/** @file
> + memcpy-like functions
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <string.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +void *
> +memcpy (
> + void *restrict Dst,
> + const void *restrict Src,
> + size_t Count
> + )
> +{
> + return CopyMem (Dst, Src, Count);
> +}
> +
> +void *
> +memmove (
> + void *Dst,
> + const void *Src,
> + size_t Count
> + )
> +{
> + return CopyMem (Dst, Src, Count);
> +}
> diff --git a/MdePkg/Library/LibcLib/String/memset.c b/MdePkg/Library/LibcLib/String/memset.c
> new file mode 100644
> index 000000000000..e66d6ade5582
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/memset.c
> @@ -0,0 +1,21 @@
> +/** @file
> + memcpy-like functions
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <string.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +void *
> +memset (
> + void *Buf,
> + int Val,
> + size_t Count
> + )
> +{
> + // The standard defines memset as converting Val into an unsigned char before storing,
> + // so this cast is entirely safe.
> + return SetMem (Buf, Count, (UINT8)Val);
> +}
> diff --git a/MdePkg/Library/LibcLib/String/strchr.c b/MdePkg/Library/LibcLib/String/strchr.c
> new file mode 100644
> index 000000000000..5e0ce7c43c98
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/strchr.c
> @@ -0,0 +1,56 @@
> +/** @file
> + strchr-like implementations
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +#include <Base.h>
> +
> +// Very quick notes:
> +// We only go through the string once for both functions
> +// They are minimal implementations (not speed optimized) of ISO C semantics
> +// strchr and strrchr also include the null terminator as part of the string
> +// so the code gets a bit clunky to handle that case specifically.
> +
> +char *
> +strchr (
> + const char *Str,
> + int Char
> + )
> +{
> + char *S;
> +
> + S = (char *)Str;
> +
> + for ( ; ; S++) {
> + if (*S == Char) {
> + return S;
> + }
> +
> + if (*S == '\0') {
> + return NULL;
> + }
> + }
> +}
> +
> +char *
> +strrchr (
> + const char *Str,
> + int Char
> + )
> +{
> + char *S, *last;
> +
> + S = (char *)Str;
> + last = NULL;
> +
> + for ( ; ; S++) {
> + if (*S == Char) {
> + last = S;
> + }
> +
> + if (*S == '\0') {
> + return last;
> + }
> + }
> +}
> diff --git a/MdePkg/Library/LibcLib/String/strcmp.c b/MdePkg/Library/LibcLib/String/strcmp.c
> new file mode 100644
> index 000000000000..9561fad389d3
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/strcmp.c
> @@ -0,0 +1,27 @@
> +/** @file
> + strcmp-like implementations
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +#include <string.h>
> +#include <Library/BaseLib.h>
> +
> +int
> +strcmp (
> + const char *Str1,
> + const char *Str2
> + )
> +{
> + return (int)AsciiStrCmp (Str1, Str2);
> +}
> +
> +int
> +strncmp (
> + const char *Str1,
> + const char *Str2,
> + size_t Count
> + )
> +{
> + return (int)AsciiStrnCmp (Str1, Str2, Count);
> +}
> diff --git a/MdePkg/Library/LibcLib/String/strcpy.c b/MdePkg/Library/LibcLib/String/strcpy.c
> new file mode 100644
> index 000000000000..767c18d6a464
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/strcpy.c
> @@ -0,0 +1,59 @@
> +/** @file
> + strcpy-like implementations
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +#include <string.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +char *
> +strcpy (
> + char *restrict Dest,
> + const char *restrict Source
> + )
> +{
> + char *Ret;
> +
> + Ret = Dest;
> +
> + for ( ; *Source != '\0'; Source++, Dest++) {
> + *Dest = *Source;
> + }
> +
> + *Dest = '\0';
> +
> + return Ret;
> +}
> +
> +char *
> +strncpy (
> + char *restrict Dest,
> + const char *restrict Source,
> + size_t Count
> + )
> +{
> + char *Ret;
> +
> + Ret = Dest;
> +
> + while (Count--) {
> + if (*Source != '\0') {
> + *Dest++ = *Source++;
> + } else {
> + *Dest++ = '\0';
> + }
> + }
> +
> + return Ret;
> +}
> +
> +char *
> +strcat (
> + char *restrict Dest,
> + const char *restrict Source
> + )
> +{
> + return strcpy (Dest + strlen (Dest), Source);
> +}
> diff --git a/MdePkg/Library/LibcLib/String/strlen.c b/MdePkg/Library/LibcLib/String/strlen.c
> new file mode 100644
> index 000000000000..a95fb7a18f7b
> --- /dev/null
> +++ b/MdePkg/Library/LibcLib/String/strlen.c
> @@ -0,0 +1,16 @@
> +/** @file
> + strlen implementation
> +
> + Copyright (c) 2023 Pedro Falcato All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +#include <string.h>
> +#include <Library/BaseLib.h>
> +
> +size_t
> +strlen (
> + const char *Str
> + )
> +{
> + return AsciiStrLen (Str);
> +}
> diff --git a/MdePkg/MdeLibs.dsc.inc b/MdePkg/MdeLibs.dsc.inc
> index 4580481cb580..f17d79286ec4 100644
> --- a/MdePkg/MdeLibs.dsc.inc
> +++ b/MdePkg/MdeLibs.dsc.inc
> @@ -16,3 +16,4 @@
> RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
> CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
> SmmCpuRendezvousLib|MdePkg/Library/SmmCpuRendezvousLibNull/SmmCpuRendezvousLibNull.inf
> + LibcLib|MdePkg/Library/LibcLib/LibcLib.inf
> diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
> index e49b2d5b5f28..8c37d89f5418 100644
> --- a/MdePkg/MdePkg.dec
> +++ b/MdePkg/MdePkg.dec
> @@ -284,6 +284,10 @@
> #
> ArmTrngLib|Include/Library/ArmTrngLib.h
>
> + ## @libraryclass Provides various bits of a C standard library.
> + #
> + LibcLib|MdePkg/Library/LibcLib/LibcLib.inf
> +
> [LibraryClasses.IA32, LibraryClasses.X64, LibraryClasses.AARCH64]
> ## @libraryclass Provides services to generate random number.
> #
> diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
> index 32a852dc466e..09828ae12647 100644
> --- a/MdePkg/MdePkg.dsc
> +++ b/MdePkg/MdePkg.dsc
> @@ -135,6 +135,7 @@
> MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
> MdePkg/Library/CcProbeLibNull/CcProbeLibNull.inf
> MdePkg/Library/SmmCpuRendezvousLibNull/SmmCpuRendezvousLibNull.inf
> + MdePkg/Library/LibcLib/LibcLib.inf
>
> [Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
> #
> --
> 2.40.0
^ permalink raw reply [flat|nested] 3+ messages in thread