* [PATCH v11 3/6] RedfishPkg/RedfishCrtLib: Redfish C runtime library
2020-12-24 14:05 [PATCH v11 0/6] jansson edk2 port Abner Chang
2020-12-24 14:05 ` [PATCH v11 1/6] RedfishPkg/Ucs2Utf8lib: UCS2 to UFT8 manipulation library Abner Chang
2020-12-24 14:05 ` [PATCH v11 2/6] edk2: jansson submodule for edk2 JSON library Abner Chang
@ 2020-12-24 14:05 ` Abner Chang
2020-12-24 14:05 ` [PATCH v11 4/6] RedfishPkg/library: EDK2 port of jansson library Abner Chang
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Abner Chang @ 2020-12-24 14:05 UTC (permalink / raw)
To: devel; +Cc: Leif Lindholm, Nickle Wang, Peter O'Hanley
Redfish CRT library is currently used by edk2 JsonLib
(open source jansson project) and edk2 RedfishLib
(libredfish open source project). Redfish CrtLib library
provides the necessary C runtime equivalent edk2 functions
for open source projects.
Signed-off-by: Abner Chang <abner.chang@hpe.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Nickle Wang <nickle.wang@hpe.com>
Cc: Peter O'Hanley <peter.ohanley@hpe.com>
Reviewed-by: Nickle Wang <nickle.wang@hpe.com>
Acked-by: Leif Lindholm <leif@nuviainc.com>
c
---
RedfishPkg/RedfishPkg.dec | 12 +
RedfishPkg/RedfishLibs.dsc.inc | 1 +
RedfishPkg/RedfishPkg.dsc | 1 +
.../RedfishCrtLib/RedfishCrtLib.inf | 38 ++
RedfishPkg/PrivateInclude/Crt/assert.h | 16 +
RedfishPkg/PrivateInclude/Crt/errno.h | 16 +
RedfishPkg/PrivateInclude/Crt/limits.h | 16 +
RedfishPkg/PrivateInclude/Crt/math.h | 16 +
RedfishPkg/PrivateInclude/Crt/stdarg.h | 15 +
RedfishPkg/PrivateInclude/Crt/stddef.h | 16 +
RedfishPkg/PrivateInclude/Crt/stdio.h | 15 +
RedfishPkg/PrivateInclude/Crt/stdlib.h | 16 +
RedfishPkg/PrivateInclude/Crt/string.h | 16 +
RedfishPkg/PrivateInclude/Crt/sys/time.h | 15 +
RedfishPkg/PrivateInclude/Crt/sys/types.h | 15 +
RedfishPkg/PrivateInclude/Crt/time.h | 15 +
.../PrivateInclude/Library/RedfishCrtLib.h | 191 ++++++
.../RedfishCrtLib/RedfishCrtLib.c | 596 ++++++++++++++++++
RedfishPkg/RedfishPkg.ci.yaml | 19 +
19 files changed, 1045 insertions(+)
create mode 100644 RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
create mode 100644 RedfishPkg/PrivateInclude/Crt/assert.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/errno.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/limits.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/math.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/stdarg.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/stddef.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/stdio.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/stdlib.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/string.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/sys/time.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/sys/types.h
create mode 100644 RedfishPkg/PrivateInclude/Crt/time.h
create mode 100644 RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
create mode 100644 RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index 3422fa6edf..1e1a96125d 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -16,10 +16,15 @@
[Includes]
Include
+[Includes.Common.Private]
+ PrivateInclude # Private header files for C RTL.
+ PrivateInclude/Crt # Private header files for C RTL.
+
[LibraryClasses]
## @libraryclass Platform Redfish Host Interface Library
# Platform implementation-specific Redfish Host Interface.
RedfishPlatformHostInterfaceLib|Include/Library/RedfishHostInterfaceLib.h
+
## @libraryclass This library provides UCS2 to UTF8 manipulation
# functions.
#
@@ -29,6 +34,13 @@
# Platform implementation-specific Redfish Credential Interface.
RedfishPlatformCredentialLib|Include/Library/RedfishCredentialLib.h
+[LibraryClasses.Common.Private]
+ ## @libraryclass Provides the private C runtime library functions.
+ # CRT library is currently used by edk2 JsonLib (open source
+ # jansson project) and edk2 RedfishLib (libredfish open source
+ # project).
+ RedfishCrtLib|PrivateInclude/Library/RedfishCrtLib.h
+
[Protocols]
## Include/Protocol/RedfishDiscover.h
gEfiRedfishDiscoverProtocolGuid = { 0x5db12509, 0x4550, 0x4347, { 0x96, 0xb3, 0x73, 0xc0, 0xff, 0x6e, 0x86, 0x9f }}
diff --git a/RedfishPkg/RedfishLibs.dsc.inc b/RedfishPkg/RedfishLibs.dsc.inc
index d4c08e18ac..4756e75b49 100644
--- a/RedfishPkg/RedfishLibs.dsc.inc
+++ b/RedfishPkg/RedfishLibs.dsc.inc
@@ -12,5 +12,6 @@
##
!if $(REDFISH_ENABLE) == TRUE
Ucs2Utf8Lib|RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
+ RedfishCrtLib|RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
!endif
diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc
index 47fab33e3d..f24f9ae8cf 100644
--- a/RedfishPkg/RedfishPkg.dsc
+++ b/RedfishPkg/RedfishPkg.dsc
@@ -50,5 +50,6 @@
RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
+ RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
!include RedfishPkg/Redfish.dsc.inc
diff --git a/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf b/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
new file mode 100644
index 0000000000..5c1c7cffa6
--- /dev/null
+++ b/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Redfish C Runtime Library for opensource projects.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishCrtLib
+ FILE_GUID = 8263B8AC-D021-425D-B337-3EC96F5DC19B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishCrtLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishCrtLib.c
+
+[LibraryClasses]
+ BaseLib
+ BaseSortLib
+ DebugLib
+ MemoryAllocationLib
+ UefiRuntimeServicesTableLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/RedfishPkg/PrivateInclude/Crt/assert.h b/RedfishPkg/PrivateInclude/Crt/assert.h
new file mode 100644
index 0000000000..9dc71e81cd
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/assert.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_ASSERT_H_
+#define REDFISH_CRT_ASSERT_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/errno.h b/RedfishPkg/PrivateInclude/Crt/errno.h
new file mode 100644
index 0000000000..b9c00ac6d8
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/errno.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_ERRNO_H_
+#define REDFISH_CRT_ERRNO_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/limits.h b/RedfishPkg/PrivateInclude/Crt/limits.h
new file mode 100644
index 0000000000..f665234dba
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/limits.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_LIMITS_H_
+#define REDFISH_CRT_LIMITS_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/math.h b/RedfishPkg/PrivateInclude/Crt/math.h
new file mode 100644
index 0000000000..6e36bfb642
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/math.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_MATH_H_
+#define REDFISH_CRT_MATH_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/stdarg.h b/RedfishPkg/PrivateInclude/Crt/stdarg.h
new file mode 100644
index 0000000000..411275b58e
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/stdarg.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_STDARG_H_
+#define REDFISH_CRT_STDARG_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/stddef.h b/RedfishPkg/PrivateInclude/Crt/stddef.h
new file mode 100644
index 0000000000..86af6f8340
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/stddef.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STDDEF_H_
+#define REDFISH_CRT_STDDEF_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/stdio.h b/RedfishPkg/PrivateInclude/Crt/stdio.h
new file mode 100644
index 0000000000..a6b8c32df6
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/stdio.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_STDIO_H_
+#define REDFISH_CRT_STDIO_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/stdlib.h b/RedfishPkg/PrivateInclude/Crt/stdlib.h
new file mode 100644
index 0000000000..b4c455ba3e
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/stdlib.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STDLIB_H_
+#define REDFISH_CRT_STDLIB_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/string.h b/RedfishPkg/PrivateInclude/Crt/string.h
new file mode 100644
index 0000000000..1def1ec1f0
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/string.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STRING_H_
+#define REDFISH_CRT_STRING_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/sys/time.h b/RedfishPkg/PrivateInclude/Crt/sys/time.h
new file mode 100644
index 0000000000..3ae791ae68
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/sys/time.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_SYS_TIME_H_
+#define REDFISH_CRT_SYS_TIME_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/sys/types.h b/RedfishPkg/PrivateInclude/Crt/sys/types.h
new file mode 100644
index 0000000000..e69510849d
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/sys/types.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_SYS_TYPES_H_
+#define REDFISH_CRT_SYS_TYPES_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Crt/time.h b/RedfishPkg/PrivateInclude/Crt/time.h
new file mode 100644
index 0000000000..e378c31ab8
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Crt/time.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_TIME_H_
+#define REDFISH_CRT_TIME_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h b/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
new file mode 100644
index 0000000000..7ec5ee09f1
--- /dev/null
+++ b/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
@@ -0,0 +1,191 @@
+/** @file
+ Redfish CRT wrapper functions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_LIB_H_
+#define REDFISH_CRT_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_STRING_SIZE 0x10000000
+
+// Minimum value for an object of type long long int.
+#define LLONG_MIN MIN_INT64
+
+// Maximum value for an object of type long long int.
+#define LLONG_MAX MAX_INT64
+
+// We dont support double on edk2
+#define HUGE_VAL 0
+
+#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || defined(MDE_CPU_RISCV64)
+//
+// With GCC we would normally use SIXTY_FOUR_BIT_LONG, but MSVC needs
+// SIXTY_FOUR_BIT, because 'long' is 32-bit and only 'long long' is
+// 64-bit. Since using 'long long' works fine on GCC too, just do that.
+//
+#define SIXTY_FOUR_BIT
+#elif defined(MDE_CPU_IA32) || defined(MDE_CPU_ARM) || defined(MDE_CPU_EBC)
+#define THIRTY_TWO_BIT
+#endif
+
+//
+// Map all va_xxxx elements to VA_xxx defined in MdePkg/Include/Base.h
+//
+#if !defined(__CC_ARM) // if va_list is not already defined
+#define va_list VA_LIST
+#define va_arg VA_ARG
+#define va_start VA_START
+#define va_end VA_END
+#else // __CC_ARM
+#define va_start(Marker, Parameter) __va_start(Marker, Parameter)
+#define va_arg(Marker, TYPE) __va_arg(Marker, TYPE)
+#define va_end(Marker) ((void)0)
+#endif
+
+//
+// Definitions for global constants used by CRT library routines
+//
+#define INT_MAX MAX_INT32 /* Maximum (signed) int value */
+#define LONG_MAX 0X7FFFFFFFL /* max value for a long */
+#define LONG_MIN (-LONG_MAX-1) /* min value for a long */
+#define ULONG_MAX 0xFFFFFFFF /* Maximum unsigned long value */
+#define CHAR_BIT 8 /* Number of bits in a char */
+
+// Maximum value for an object of type unsigned long long int.
+#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL // 2^64 - 1
+// Maximum value for an object of type unsigned char.
+#define UCHAR_MAX 255 // 2^8 - 1
+
+//
+// Basic types mapping
+//
+typedef UINTN size_t;
+typedef INTN ssize_t;
+typedef INT32 time_t;
+typedef UINT8 __uint8_t;
+typedef UINT8 sa_family_t;
+typedef UINT32 uid_t;
+typedef UINT32 gid_t;
+typedef INT32 int32_t;
+typedef UINT32 uint32_t;
+typedef UINT16 uint16_t;
+typedef UINT8 uint8_t;
+typedef enum {false, true} bool;
+
+//
+// File operations are not required for EFI building,
+// so FILE is mapped to VOID * to pass build
+//
+typedef VOID *FILE;
+
+//
+// Global variables
+//
+extern int errno;
+extern FILE *stderr;
+
+//
+// Function prototypes of CRT Library routines
+//
+void *malloc (size_t);
+void *realloc (void *, size_t);
+void *calloc (size_t Num, size_t Size);
+void free (void *);
+void *memset (void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+int isdigit (int);
+int isspace (int);
+int tolower (int);
+int isupper (int);
+int isxdigit (int);
+int isalnum (int);
+void *memcpy (void *, const void *, size_t);
+void *memset (void *, int, size_t);
+void *memchr (const void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+void *memmove (void *, const void *, size_t);
+int strcmp (const char *, const char *);
+int strncmp (const char *, const char *, size_t);
+char *strcpy (char *, const char *);
+size_t strlen (const char *);
+char *strcat (char *, const char *);
+char *strchr (const char *, int);
+int strcasecmp (const char *, const char *);
+int strncasecmp (const char *, const char *, size_t);
+char *strncpy (char *, size_t, const char *, size_t);
+int strncmp (const char *, const char *, size_t);
+char *strrchr (const char *, int);
+unsigned long strtoul (const char *, char **, int);
+char * strstr (const char *s1 , const char *s2);
+long strtol (const char *, char **, int);
+char *strerror (int);
+size_t strspn (const char *, const char *);
+char * strdup (const char *str);
+char * strpbrk (const char *s1, const char *s2);
+unsigned long long strtoull(const char * nptr, char ** endptr, int base);
+long long strtoll (const char * nptr, char ** endptr, int base);
+long strtol (const char * nptr, char ** endptr, int base);
+double strtod (const char * __restrict nptr, char ** __restrict endptr);
+size_t strcspn (const char *, const char *);
+int printf (const char *, ...);
+int sscanf (const char *, const char *, ...);
+FILE *fopen (const char *, const char *);
+size_t fread (void *, size_t, size_t, FILE *);
+size_t fwrite (const void *, size_t, size_t, FILE *);
+int fclose (FILE *);
+int fprintf (FILE *, const char *, ...);
+int fgetc (FILE * _File);
+uid_t getuid (void);
+uid_t geteuid (void);
+gid_t getgid (void);
+gid_t getegid (void);
+void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
+char *getenv (const char *);
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+void abort (void) __attribute__((__noreturn__));
+#else
+void abort (void);
+#endif
+int toupper (int);
+int Digit2Val (int);
+time_t time (time_t *);
+
+//
+// Macros that directly map functions to BaseLib, BaseMemoryLib, and DebugLib functions
+//
+#define strcmp AsciiStrCmp
+#define memcpy(dest,source,count) CopyMem(dest,source,(UINTN)(count))
+#define memset(dest,ch,count) SetMem(dest,(UINTN)(count),(UINT8)(ch))
+#define memchr(buf,ch,count) ScanMem8(buf,(UINTN)(count),(UINT8)ch)
+#define memcmp(buf1,buf2,count) (int)(CompareMem(buf1,buf2,(UINTN)(count)))
+#define memmove(dest,source,count) CopyMem(dest,source,(UINTN)(count))
+#define strlen(str) (size_t)(AsciiStrnLenS(str,MAX_STRING_SIZE))
+#define strcpy(strDest,strSource) AsciiStrCpyS(strDest,(strlen(strSource)+1),strSource)
+#define strncpy(strDest,strSource,count) AsciiStrnCpyS(strDest,(UINTN)count,strSource,(UINTN)count)
+#define strncpys(strDest, DestLen, strSource,count) AsciiStrnCpyS(strDest,DestLen,strSource,(UINTN)count)
+#define strcat(strDest,strSource) AsciiStrCatS(strDest,(strlen(strSource)+strlen(strDest)+1),strSource)
+#define strchr(str,ch) ScanMem8((VOID *)(str),AsciiStrSize(str),(UINT8)ch)
+#define strcasecmp(str1,str2) (int)AsciiStriCmp(str1,str2)
+#define strstr(s1,s2) AsciiStrStr(s1,s2)
+#define snprintf(buf,len,...) AsciiSPrint(buf,len,__VA_ARGS__)
+#define vsnprintf(buf,len,format,marker) AsciiVSPrint((buf),(len),(format),(marker))
+#define assert(expression) ASSERT(expression)
+#define offsetof(type,member) OFFSET_OF(type,member)
+
+#define EOF (-1)
+
+extern int errno;
+
+#define ERANGE 34 /* 34 Result too large */
+
+#endif
diff --git a/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c b/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
new file mode 100644
index 0000000000..0fdd1fc5f1
--- /dev/null
+++ b/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
@@ -0,0 +1,596 @@
+/** @file
+ CRT wrapper functions for system call,the string operation functions
+ are remodeled after edk2-libc.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/RedfishCrtLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+int errno = 0;
+
+/**
+ Determine if a particular character is an alphanumeric character
+ @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
+**/
+int isalnum (int c)
+{
+ //
+ // <alnum> ::= [0-9] | [a-z] | [A-Z]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (('a' <= (c)) && ((c) <= 'z')) ||
+ (('A' <= (c)) && ((c) <= 'Z')));
+}
+
+/**
+ Determine if a particular character is a digital character
+
+ @return Returns 1 if c is an digital character, otherwise returns 0.
+**/
+int isdchar (int c)
+{
+ //
+ // [0-9] | [e +-.]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (c == 'e') || (c == 'E') ||
+ (c == '+') || (c == '-') ||
+ (c == '.'));
+}
+
+/**
+ Determine if a particular character is a space character
+
+ @return Returns 1 if c is a space character
+**/
+int isspace (int c)
+{
+ //
+ // <space> ::= [ ]
+ //
+ return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f');
+}
+
+/**
+ Allocates memory blocks
+*/
+void *malloc (size_t size)
+{
+ return AllocatePool ((UINTN) size);
+}
+
+/**
+ De-allocates or frees a memory block
+*/
+void free (void *ptr)
+{
+ //
+ // In Standard C, free() handles a null pointer argument transparently. This
+ // is not true of FreePool() below, so protect it.
+ //
+ if (ptr != NULL) {
+ FreePool (ptr);
+ }
+}
+
+/**
+ NetBSD Compatibility Function strdup creates a duplicate copy of a string.
+
+ @return Returns the pointer to duplicated string.
+**/
+char * strdup(const char *str)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if ((copy = malloc(len)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
+}
+
+/** The toupper function converts a lowercase letter to a corresponding
+ uppercase letter.
+
+ @param[in] c The character to be converted.
+
+ @return If the argument is a character for which islower is true and
+ there are one or more corresponding characters, as specified by
+ the current locale, for which isupper is true, the toupper
+ function returns one of the corresponding characters (always the
+ same one for any given locale); otherwise, the argument is
+ returned unchanged.
+**/
+int
+toupper(
+ IN int c
+ )
+{
+ if ( (c >= 'a') && (c <= 'z') ) {
+ c = c - ('a' - 'A');
+ }
+ return c;
+}
+
+/**
+ Digit to a value.
+
+ @return Returns the value of digit.
+**/
+int
+Digit2Val( int c)
+{
+ if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { /* If c is one of [A-Za-z]... */
+ c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
+ }
+ return c - '0'; // Value returned is between 0 and 35, inclusive.
+}
+
+
+/** The strtoll function converts the initial portion of the string pointed to
+ by nptr to long long int representation.
+
+ See the description for strtol for more information.
+
+ @return The strtoll function returns the converted value, if any. If no
+ conversion could be performed, zero is returned. If the correct
+ value is outside the range of representable values, LLONG_MIN or
+ LLONG_MAX is returned (according to the sign of the value, if any),
+ and the value of the macro ERANGE is stored in errno.
+**/
+long long
+strtoll(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ long long Result = 0;
+ long long Previous;
+ int temp;
+ BOOLEAN Negative = FALSE;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional sign followed by digits.
+ if(*nptr == '+') {
+ Negative = FALSE;
+ ++nptr;
+ }
+ else if(*nptr == '-') {
+ Negative = TRUE;
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = MultS64x64 (Result, base) + (long long int)temp;
+ if( Result <= Previous) { // Detect Overflow
+ if(Negative) {
+ Result = LLONG_MIN;
+ }
+ else {
+ Result = LLONG_MAX;
+ }
+ Negative = FALSE;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+ if(Negative) {
+ Result = -Result;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/** The strtol, strtoll, strtoul, and strtoull functions convert the initial
+ portion of the string pointed to by nptr to long int, long long int,
+ unsigned long int, and unsigned long long int representation, respectively.
+ First, they decompose the input string into three parts: an initial,
+ possibly empty, sequence of white-space characters (as specified by the
+ isspace function), a subject sequence resembling an integer represented in
+ some radix determined by the value of base, and a final string of one or
+ more unrecognized characters, including the terminating null character of
+ the input string. Then, they attempt to convert the subject sequence to an
+ integer, and return the result.
+
+ If the value of base is zero, the expected form of the subject sequence is
+ that of an integer constant, optionally preceded
+ by a plus or minus sign, but not including an integer suffix. If the value
+ of base is between 2 and 36 (inclusive), the expected form of the subject
+ sequence is a sequence of letters and digits representing an integer with
+ the radix specified by base, optionally preceded by a plus or minus sign,
+ but not including an integer suffix. The letters from a (or A) through z
+ (or Z) are ascribed the values 10 through 35; only letters and digits whose
+ ascribed values are less than that of base are permitted. If the value of
+ base is 16, the characters 0x or 0X may optionally precede the sequence of
+ letters and digits, following the sign if present.
+
+ The subject sequence is defined as the longest initial subsequence of the
+ input string, starting with the first non-white-space character, that is of
+ the expected form. The subject sequence contains no characters if the input
+ string is empty or consists entirely of white space, or if the first
+ non-white-space character is other than a sign or a permissible letter or digit.
+
+ If the subject sequence has the expected form and the value of base is
+ zero, the sequence of characters starting with the first digit is
+ interpreted as an integer constant. If the subject sequence has the
+ expected form and the value of base is between 2 and 36, it is used as the
+ base for conversion, ascribing to each letter its value as given above. If
+ the subject sequence begins with a minus sign, the value resulting from the
+ conversion is negated (in the return type). A pointer to the final string
+ is stored in the object pointed to by endptr, provided that endptr is
+ not a null pointer.
+
+ In other than the "C" locale, additional locale-specific subject sequence
+ forms may be accepted.
+
+ If the subject sequence is empty or does not have the expected form, no
+ conversion is performed; the value of nptr is stored in the object pointed
+ to by endptr, provided that endptr is not a null pointer.
+
+ @return The strtol, strtoll, strtoul, and strtoull functions return the
+ converted value, if any. If no conversion could be performed, zero
+ is returned. If the correct value is outside the range of
+ representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
+ ULONG_MAX, or ULLONG_MAX is returned (according to the return type
+ and sign of the value, if any), and the value of the macro ERANGE
+ is stored in errno.
+**/
+long
+strtol(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ long Result = 0;
+ long Previous;
+ int temp;
+ BOOLEAN Negative = FALSE;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional sign followed by digits.
+ if(*nptr == '+') {
+ Negative = FALSE;
+ ++nptr;
+ }
+ else if(*nptr == '-') {
+ Negative = TRUE;
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = (Result * base) + (long int)temp;
+ if( Result <= Previous) { // Detect Overflow
+ if(Negative) {
+ Result = LONG_MIN;
+ }
+ else {
+ Result = LONG_MAX;
+ }
+ Negative = FALSE;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+ if(Negative) {
+ Result = -Result;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/** The strtoull function converts the initial portion of the string pointed to
+ by nptr to unsigned long long int representation.
+
+ See the description for strtol for more information.
+
+ @return The strtoull function returns the converted value, if any. If no
+ conversion could be performed, zero is returned. If the correct
+ value is outside the range of representable values, ULLONG_MAX is
+ returned and the value of the macro ERANGE is stored in errno.
+**/
+unsigned long long
+strtoull(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ unsigned long long Result = 0;
+ unsigned long long Previous;
+ int temp;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional + sign followed by digits.
+ if(*nptr == '+') {
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = DivU64x32 (Result, base) + (unsigned long long)temp;
+ if( Result < Previous) { // If we overflowed
+ Result = ULLONG_MAX;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/**
+ edk2 Jansson port does not support doubles, simply return 0.
+
+ These conversion functions convert the initial portion of the string
+ pointed to by nptr to double, float, and long double representation,
+ respectively.
+
+ The strtod(), strtof(), and strtold() functions return the converted
+ value, if any.
+
+ If endptr is not NULL, a pointer to the character after the last charac-
+ ter used in the conversion is stored in the location referenced by
+ endptr.
+
+ If no conversion is performed, zero is returned and the value of nptr is
+ stored in the location referenced by endptr.
+
+ If the correct value would cause overflow, plus or minus HUGE_VAL,
+ HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
+ the return value), and ERANGE is stored in errno. If the correct value
+ would cause underflow, zero is returned and ERANGE is stored in errno.
+
+ @return Return 0.
+**/
+double
+strtod (const char * __restrict nptr, char ** __restrict endptr) {
+
+ DEBUG((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));
+ ASSERT(FALSE);
+ return (double)0;
+}
+
+/**
+ Allocate and zero-initialize array.
+**/
+void *
+calloc(size_t Num, size_t Size)
+{
+ void *RetVal;
+ size_t NumSize;
+
+ NumSize = Num * Size;
+ RetVal = NULL;
+ if (NumSize != 0) {
+ RetVal = malloc(NumSize);
+ if( RetVal != NULL) {
+ (VOID)ZeroMem( RetVal, NumSize);
+ }
+ }
+ DEBUG((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));
+
+ return RetVal;
+}
+
+//
+// The arrays give the cumulative number of days up to the first of the
+// month number used as the index (1 -> 12) for regular and leap years.
+// The value at index 13 is for the whole year.
+//
+UINTN CumulativeDays[2][14] = {
+ {
+ 0,
+ 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
+ },
+ {
+ 0,
+ 0,
+ 31,
+ 31 + 29,
+ 31 + 29 + 31,
+ 31 + 29 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
+ }
+};
+
+#define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define SECSPERMIN (60)
+#define SECSPERHOUR (60 * 60)
+#define SECSPERDAY (24 * SECSPERHOUR)
+
+/**
+ Get the system time as seconds elapsed since midnight, January 1, 1970.
+**/
+time_t time (time_t *timer)
+{
+ EFI_TIME Time;
+ time_t CalTime;
+ UINTN Year;
+
+ //
+ // Get the current time and date information
+ //
+ gRT->GetTime (&Time, NULL);
+
+ //
+ // Years Handling
+ // UTime should now be set to 00:00:00 on Jan 1 of the current year.
+ //
+ for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
+ CalTime = CalTime + (time_t)(CumulativeDays[IsLeap(Year)][13] * SECSPERDAY);
+ }
+
+ //
+ // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
+ //
+ CalTime = CalTime +
+ (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
+ (time_t)(CumulativeDays[IsLeap(Time.Year)][Time.Month] * SECSPERDAY) +
+ (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
+ (time_t)(Time.Hour * SECSPERHOUR) +
+ (time_t)(Time.Minute * 60) +
+ (time_t)Time.Second;
+
+ if (timer != NULL) {
+ *timer = CalTime;
+ }
+
+ return CalTime;
+}
+
+/**
+ Performs a quick sort
+**/
+void qsort (void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
+{
+
+ ASSERT (base != NULL);
+ ASSERT (compare != NULL);
+
+ PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);
+ return;
+}
+
+/**
+ Get character from stream, we don't support file operastion on edk2 JSON library.
+
+ @return Returns the character currently pointed by the internal file position indicator of the specified stream
+
+**/
+int fgetc(FILE * _File){
+ return 0;
+}
diff --git a/RedfishPkg/RedfishPkg.ci.yaml b/RedfishPkg/RedfishPkg.ci.yaml
index 20c297ad22..e410d1a608 100644
--- a/RedfishPkg/RedfishPkg.ci.yaml
+++ b/RedfishPkg/RedfishPkg.ci.yaml
@@ -17,6 +17,25 @@
],
## Both file path and directory path are accepted.
"IgnoreFiles": [
+ ## Below are files incorporated with open source which are
+ ## not edk2 coding standard compliant.
+ ##
+ ## EDK2 CRT library which is not edk2 coding
+ ## standard compliant.
+ ## C runtime library for RedfishPkg modules
+ "PrivateInclude/Crt/sys",
+ "PrivateInclude/Crt/assert.h",
+ "PrivateInclude/Crt/errno.h",
+ "PrivateInclude/Crt/limits.h",
+ "PrivateInclude/Crt/math.h",
+ "PrivateInclude/Crt/stdarg.h",
+ "PrivateInclude/Crt/stddef.h",
+ "PrivateInclude/Crt/stdio.h",
+ "PrivateInclude/Crt/stdlib.h",
+ "PrivateInclude/Crt/string.h",
+ "PrivateInclude/Crt/time.h",
+ "PrivateInclude/Library/RedfishCrtLib.h",
+ "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c"
]
},
"CompilerPlugin": {
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v11 4/6] RedfishPkg/library: EDK2 port of jansson library
2020-12-24 14:05 [PATCH v11 0/6] jansson edk2 port Abner Chang
` (2 preceding siblings ...)
2020-12-24 14:05 ` [PATCH v11 3/6] RedfishPkg/RedfishCrtLib: Redfish C runtime library Abner Chang
@ 2020-12-24 14:05 ` Abner Chang
2020-12-24 14:05 ` [PATCH v11 5/6] RedfishPkg: Add EDK2 port of jansson library to build Abner Chang
2020-12-24 14:06 ` [PATCH v11 6/6] .pytool: Add required submodule for JsonLib Abner Chang
5 siblings, 0 replies; 7+ messages in thread
From: Abner Chang @ 2020-12-24 14:05 UTC (permalink / raw)
To: devel; +Cc: Leif Lindholm, Nickle Wang, Peter O'Hanley
edk2 JsonLib which is the edk2 port of open source
jansson library.
(https://github.com/akheron/jansson)
jansson library is the open source project to manipulate
JSON data structure.
Signed-off-by: Abner Chang <abner.chang@hpe.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Nickle Wang <nickle.wang@hpe.com>
Cc: Peter O'Hanley <peter.ohanley@hpe.com>
Reviewed-by: Nickle Wang <nickle.wang@hpe.com>
Acked-by: Leif Lindholm <leif@nuviainc.com>
---
RedfishPkg/RedfishPkg.dec | 12 +
RedfishPkg/Library/JsonLib/JsonLib.inf | 86 ++
RedfishPkg/Include/Library/JsonLib.h | 779 ++++++++++++
RedfishPkg/Library/JsonLib/jansson_config.h | 41 +
.../Library/JsonLib/jansson_private_config.h | 19 +
RedfishPkg/Library/JsonLib/JsonLib.c | 957 ++++++++++++++
RedfishPkg/Library/JsonLib/load.c | 1111 +++++++++++++++++
RedfishPkg/Library/JsonLib/Readme.rst | 35 +
RedfishPkg/RedfishPkg.ci.yaml | 8 +-
9 files changed, 3047 insertions(+), 1 deletion(-)
create mode 100644 RedfishPkg/Library/JsonLib/JsonLib.inf
create mode 100644 RedfishPkg/Include/Library/JsonLib.h
create mode 100644 RedfishPkg/Library/JsonLib/jansson_config.h
create mode 100644 RedfishPkg/Library/JsonLib/jansson_private_config.h
create mode 100644 RedfishPkg/Library/JsonLib/JsonLib.c
create mode 100644 RedfishPkg/Library/JsonLib/load.c
create mode 100644 RedfishPkg/Library/JsonLib/Readme.rst
diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index 1e1a96125d..cc3ccb2058 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -19,6 +19,13 @@
[Includes.Common.Private]
PrivateInclude # Private header files for C RTL.
PrivateInclude/Crt # Private header files for C RTL.
+ Library/JsonLib # Private header files for jansson
+ # configuration files.
+ # - jansson_config.h
+ # - jansson_private_config.h
+ # jansson.h refers to above two configuration
+ # files for building platform jansson library.
+ Library/JsonLib/jansson/src # For referring to jannson.h
[LibraryClasses]
## @libraryclass Platform Redfish Host Interface Library
@@ -34,6 +41,11 @@
# Platform implementation-specific Redfish Credential Interface.
RedfishPlatformCredentialLib|Include/Library/RedfishCredentialLib.h
+ ## @libraryclass Provides the library functions based on third party
+ # jansson library to manipulate JSON data structure.
+ #
+ JsonLib|Include/Library/JsonLib.h
+
[LibraryClasses.Common.Private]
## @libraryclass Provides the private C runtime library functions.
# CRT library is currently used by edk2 JsonLib (open source
diff --git a/RedfishPkg/Library/JsonLib/JsonLib.inf b/RedfishPkg/Library/JsonLib/JsonLib.inf
new file mode 100644
index 0000000000..48b094a78a
--- /dev/null
+++ b/RedfishPkg/Library/JsonLib/JsonLib.inf
@@ -0,0 +1,86 @@
+## @file
+# Thirty party Jansson library for JSON operations.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = JsonLib
+ FILE_GUID = F5E36815-305A-4C5A-9D75-4F2149E45255
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = JsonLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ #
+ # Below are the source code of third
+ # party jansson library.
+ #
+ jansson/src/dump.c
+ jansson/src/error.c
+ jansson/src/hashtable.c
+ jansson/src/hashtable_seed.c
+ jansson/src/memory.c
+ jansson/src/pack_unpack.c
+ jansson/src/strbuffer.c
+ jansson/src/strconv.c
+ jansson/src/utf.c
+ jansson/src/value.c
+ jansson/src/version.c
+ #
+ # Below are the source of edk2 JsonLib.
+ #
+ JsonLib.c
+ jansson_config.h
+ jansson_private_config.h
+ #
+ # Below is the source code override to fix the build issue.
+ # Add code in load.c to conditionally use stdin according
+ # to HAVE_UNISTD_H macro. The PR is submitted to jansson
+ # open source community.
+ # https://github.com/akheron/jansson/pull/558
+ #
+ load.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ Ucs2Utf8Lib
+ RedfishCrtLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+
+[BuildOptions]
+ #
+ # Disables the following Visual Studio compiler warnings
+ # so we do not break the build with /WX option:
+ # C4090: 'function' : different 'const' qualifiers
+ # C4244: conversion from type1 to type2, possible loss of data
+ # C4334: 32-bit shift implicitly converted to 64-bit
+ # C4204: nonstandard extension used: non-constant aggregate initializer
+ #
+ # Define macro HAVE_CONFIG_H to include jansson_private_config.h to build.
+ # Undefined _WIN32, WIN64, _MSC_VER macros
+ # On GCC, no error on the unused-function and unused-but-set-variable.
+ #
+ MSFT:*_*_X64_CC_FLAGS = /wd4204 /wd4244 /wd4090 /wd4334 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER
+ MSFT:*_*_IA32_CC_FLAGS = /wd4204 /wd4244 /wd4090 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER
+ GCC:*_*_*_CC_FLAGS = -Wno-unused-function -Wno-unused-but-set-variable
+
diff --git a/RedfishPkg/Include/Library/JsonLib.h b/RedfishPkg/Include/Library/JsonLib.h
new file mode 100644
index 0000000000..3c10f67d27
--- /dev/null
+++ b/RedfishPkg/Include/Library/JsonLib.h
@@ -0,0 +1,779 @@
+/** @file
+ APIs for JSON operations.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef JSON_LIB_H_
+#define JSON_LIB_H_
+
+typedef VOID* EDKII_JSON_VALUE;
+typedef VOID* EDKII_JSON_ARRAY;
+typedef VOID* EDKII_JSON_OBJECT;
+
+///
+/// Map to json_int_t in jansson.h
+///
+typedef INT64 EDKII_JSON_INT_T; // #JSON_INTEGER_IS_LONG_LONG is set to 1
+ // in jansson_Config.h
+
+///
+/// Map to the definitions in jansson.h
+/// See below URI for the JSON encoding flags reference.
+/// https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+///
+#define EDKII_JSON_MAX_INDENT 0x1F
+#define EDKII_JSON_INDENT(n) ((n) & EDKII_JSON_MAX_INDENT)
+
+#define EDKII_JSON_COMPACT 0x20
+#define EDKII_JSON_ENSURE_ASCII 0x40
+#define EDKII_JSON_SORT_KEYS 0x80
+#define EDKII_JSON_PRESERVE_ORDER 0x100
+#define EDKII_JSON_ENCODE_ANY 0x200
+#define EDKII_JSON_ESCAPE_SLASH 0x400
+#define EDKII_JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
+#define EDKII_JSON_EMBED 0x10000
+
+///
+/// Map to the definitions in jansson.h
+/// See below URI for the JSON decoding flags reference.
+/// https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+///
+#define EDKII_JSON_REJECT_DUPLICATES 0x1
+#define EDKII_JSON_DISABLE_EOF_CHECK 0x2
+#define EDKII_JSON_DECODE_ANY 0x4
+#define EDKII_JSON_DECODE_INT_AS_REAL 0x8
+#define EDKII_JSON_ALLOW_NUL 0x10
+
+#define EDKII_JSON_ARRAY_FOREACH(Array, Index, Value) \
+ for(Index = 0; \
+ Index < JsonArrayCount(Array) && (Value = JsonArrayGetValue(Array, Index)); \
+ Index++)
+
+///
+/// Map to the json_error_t in jansson.h
+///
+#define EDKII_JSON_ERROR_TEXT_LENGTH 160
+#define EDKII_JSON_ERROR_SOURCE_LENGTH 80
+typedef struct {
+ INTN Line;
+ INTN Column;
+ INTN Position;
+ CHAR8 Source [EDKII_JSON_ERROR_SOURCE_LENGTH];
+ CHAR8 Text [EDKII_JSON_ERROR_TEXT_LENGTH];
+} EDKII_JSON_ERROR;
+
+///
+/// Map to the json_type in jansson.h
+///
+typedef enum {
+ EdkiiJsonTypeObject,
+ EdkiiJsonTypeArray,
+ EdkiiJsonTypeString,
+ EdkiiJsonTypeInteger,
+ EdkiiJsonTypeReal,
+ EdkiiJsonTypeTrue,
+ EdkiiJsonTypeFalse,
+ EdkiiJsonTypeNull
+} EDKII_JSON_TYPE;
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON array,
+ or NULL on error. Initially, the array is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitArray (
+ VOID
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON object,
+ or NULL on error. Initially, the object is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitObject (
+ VOID
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input string must be NULL terminated Ascii format, non-Ascii characters will
+ be processed as an error. Unicode characters can also be represented by Ascii string
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Ascii string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitAsciiString (
+ IN CONST CHAR8 *String
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input must be a NULL terminated UCS2 format Unicode string.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Unicode string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitUnicodeString (
+ IN CHAR16 *String
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON integer,
+ or NULL on error.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] Value The integer to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON number or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNumber (
+ IN INT64 Value
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON boolean,
+ or NULL on error.
+
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.
+
+ @param[in] Value The boolean value to initialize.
+
+ @retval The created JSON value which contains a JSON boolean or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitBoolean (
+ IN BOOLEAN Value
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON NULL,
+ or NULL on error.
+
+ NULL JSON value is kept as static value, and no need to do any cleanup work.
+
+ @retval The created NULL JSON value.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNull (
+ VOID
+ );
+
+/**
+ The function is used to decrease the reference count of a JSON value by one, and once
+ this reference count drops to zero, the value is destroyed and it can no longer be used.
+ If this destroyed value is object type or array type, reference counts for all containing
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed
+ since they are static values kept in memory.
+
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a
+ value is kept for use, its reference count is incremented, and when the value is no longer
+ needed, the reference count is decremented. When the reference count drops to zero, there are
+ no references left, and the value can be destroyed.
+
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message
+ to inform caller the NULL value is passed in.
+
+ @param[in] Json The JSON value to be freed. json_decref may return without any
+ changes if Json is NULL.
+
+**/
+VOID
+EFIAPI
+JsonValueFree (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to create a fresh copy of a JSON value, and all child values are deep
+ copied in a recursive fashion. It should be called when this JSON value might be modified
+ in later use, but the original still wants to be used in somewhere else.
+
+ Reference counts of the returned root JSON value and all child values will be set to 1, and
+ caller needs to cleanup the root value by calling JsonValueFree().
+
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some
+ performance issues, user should avoid unnecessary calls to this function unless it is really
+ needed.
+
+ @param[in] Json The JSON value to be cloned.
+
+ @retval Return the cloned JSON value, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueClone (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON array.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON array.
+ @retval FALSE The JSON value doesn't contain a JSON array.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsArray (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON object.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON object.
+ @retval FALSE The JSON value doesn't contain a JSON object.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsObject (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON Value contains a string, Ascii or
+ Unicode format is not differentiated.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON string.
+ @retval FALSE The JSON value doesn't contain a JSON string.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON number.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value is contains JSON number.
+ @retval FALSE The JSON value doesn't contain a JSON number.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNumber (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON boolean.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON boolean.
+ @retval FALSE The JSON value doesn't contain a JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsBoolean (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON NULL.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON NULL.
+ @retval FALSE The JSON value doesn't contain a JSON NULL.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNull (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated array in an array type JSON value.
+
+ Any changes to the returned array will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated array in JSON value or NULL.
+
+**/
+EDKII_JSON_ARRAY
+EFIAPI
+JsonValueGetArray (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated object in an object type JSON value.
+
+ Any changes to the returned object will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated object in JSON value or NULL.
+
+**/
+EDKII_JSON_OBJECT
+EFIAPI
+JsonValueGetObject (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated Ascii string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL.
+
+**/
+CONST CHAR8 *
+EFIAPI
+JsonValueGetAsciiString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated Unicode string in a string type JSON value.
+
+ Caller can do any changes to the returned string without any impact to the original JSON
+ value, and caller needs to free the returned string using FreePool().
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Unicode string in JSON value or NULL.
+
+**/
+CHAR16*
+EFIAPI
+JsonValueGetUnicodeString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated integer in a number type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will
+ ASSERT() and return 0.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated number in JSON value.
+
+**/
+INT64
+EFIAPI
+JsonValueGetNumber (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated boolean in a boolean type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will
+ ASSERT() and return FALSE.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated value of JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueGetBoolean (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL on errors.
+
+**/
+CONST CHAR8*
+EFIAPI
+JsonValueGetString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or
+ not a JSON object.
+
+ @param[in] JsonObject The provided JSON object.
+
+ @retval Return the number of elements in this JSON object or 0.
+
+**/
+UINTN
+EFIAPI
+JsonObjectSize (
+ IN EDKII_JSON_OBJECT JsonObject
+ );
+
+/**
+ The function is used to enumerate all keys in a JSON object.
+
+ Caller should be responsible to free the returned key array reference using
+ FreePool(). But contained keys are read only and must not be modified or freed.
+
+ @param[in] JsonObj The provided JSON object for enumeration.
+ @param[out] KeyCount The count of keys in this JSON object.
+
+ @retval Return an array of the enumerated keys in this JSON object or NULL if
+ JsonObj is not an JSON object, key count is zero or on other errors.
+
+**/
+CHAR8**
+JsonObjectGetKeys (
+ IN EDKII_JSON_OBJECT JsonObj,
+ OUT UINTN *KeyCount
+ );
+
+/**
+ The function is used to get a JSON value corresponding to the input key from a JSON object.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when
+ Key-Value is not found in this JSON object.
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be retrieved.
+
+ @retval Return the corresponding JSON value to key, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectGetValue (
+ IN CONST EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key
+ );
+
+/**
+ The function is used to set a JSON value corresponding to the input key from a JSON object,
+ and the reference count of this value will be increased by 1.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed
+ from this object and thus its' reference count will be decreased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be set.
+ @param[in] Json The JSON value to set to this JSON object mapped by key.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonObjectSetValue (
+ IN EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key,
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray
+ is NULL or not a JSON array.
+
+ @param[in] JsonArray The provided JSON array.
+
+ @retval Return the number of elements in this JSON array or 0.
+
+**/
+UINTN
+EFIAPI
+JsonArrayCount (
+ IN EDKII_JSON_ARRAY JsonArray
+ );
+
+/**
+ The function is used to return the JSON value in the array at position index. The valid range
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.
+
+ @param[in] JsonArray The provided JSON Array.
+
+ @retval Return the JSON value located in the Index position or
+ NULL if JsonArray is not an array or no items in the array.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonArrayGetValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ );
+
+/**
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of
+ array by 1. The reference count of this value will be increased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON object.
+ @param[in] Json The JSON value to append.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayAppendValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to remove a JSON value at position index, shifting the elements after index
+ one position towards the start of the array. The reference count of this value will be decreased
+ by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON array.
+ @param[in] Index The Index position before removement.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON array has been removed at position index.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayRemoveValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ );
+
+/**
+ Dump JSON to a buffer.
+
+ @param[in] JsonValue The provided JSON value.
+ @param[in] Flags The Index position before removement. The value
+ could be the combination of below flags.
+ - EDKII_JSON_INDENT(n)
+ - EDKII_JSON_COMPACT
+ - EDKII_JSON_ENSURE_ASCII
+ - EDKII_JSON_SORT_KEYS
+ - EDKII_JSON_PRESERVE_ORDER
+ - EDKII_JSON_ENCODE_ANY
+ - EDKII_JSON_ESCAPE_SLASH
+ - EDKII_JSON_REAL_PRECISION(n)
+ - EDKII_JSON_EMBED
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer
+ contain JSON paylaod in ASCII string. The return
+ value must be freed by the caller FreePool().
+**/
+CHAR8 *
+EFIAPI
+JsonDumpString (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN UINTN Flags
+ );
+
+/**
+ Load JSON from a buffer.
+
+ @param[in] Buffer Bufffer to the JSON payload
+ @param[in] BufferLen Length of the buffer
+ @param[in] Flags Flag of loading JSON buffer, the value
+ could be the combination of below flags.
+ - EDKII_JSON_REJECT_DUPLICATES
+ - EDKII_JSON_DISABLE_EOF_CHECK
+ - EDKII_JSON_DECODE_ANY
+ - EDKII_JSON_DECODE_INT_AS_REAL
+ - EDKII_JSON_ALLOW_NUL
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure
+
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadBuffer (
+ IN CONST CHAR8 *Buffer,
+ IN UINTN BufferLen,
+ IN UINTN Flags,
+ IN OUT EDKII_JSON_ERROR *Error
+ );
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ when the value is no longer needed, the reference count is decremented.
+ When the reference count drops to zero, there are no references left and the
+ value can be destroyed.
+
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as
+ a call to json_decref() drops the reference count to zero, the value is
+ destroyed and it can no longer be used.
+
+ @param[in] JsonValue JSON value
+**/
+VOID
+EFIAPI
+JsonDecreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),
+ its reference count is incremented.
+
+ This function increment the reference count of json if it's not NULL.
+ Returns EDKII_JSON_VALUE.
+
+ @param[in] JsonValue JSON value
+ @retval EDKII_JSON_VALUE of itself
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonIncreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+/**
+ Returns an opaque iterator which can be used to iterate over all key-value pairs
+ in object, or NULL if object is empty
+
+ @param[in] JsonValue JSON value
+**/
+VOID *
+EFIAPI
+JsonObjectIterator (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+
+/**
+ Extract the associated value from iterator.
+
+ @param[in] Iterator Iterator pointer
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectIteratorValue (
+ IN VOID *Iterator
+ );
+
+/**
+ Returns an iterator pointing to the next key-value pair in object after iter,
+ or NULL if the whole object has been iterated through.
+
+ @param[in] JsonValue JSON value
+ @param[in] Iterator Iterator pointer
+ @retval Iterator pointer
+**/
+VOID *
+JsonObjectIteratorNext (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN VOID *Iterator
+ );
+
+/**
+ Returns the json type of this json value
+
+ @param[in] JsonValue JSON value
+ @retval JSON type returned
+**/
+EDKII_JSON_TYPE
+EFIAPI
+JsonGetType(
+ IN EDKII_JSON_VALUE JsonValue
+ );
+#endif
diff --git a/RedfishPkg/Library/JsonLib/jansson_config.h b/RedfishPkg/Library/JsonLib/jansson_config.h
new file mode 100644
index 0000000000..c66d3ced9b
--- /dev/null
+++ b/RedfishPkg/Library/JsonLib/jansson_config.h
@@ -0,0 +1,41 @@
+/** @file This is the configuration file for building jansson library.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+#ifndef JANSSON_CONFIG_H_
+#define JANSSON_CONFIG_H_
+
+///
+/// We don't support inline JSON on edk2
+///
+#define JSON_INLINE
+
+///
+/// We support long long on edk2
+///
+#define JSON_INTEGER_IS_LONG_LONG 1
+
+///
+/// We don't support locale on edk2
+///
+#define JSON_HAVE_LOCALECONV 0
+
+///
+/// We don't support atomic builtins on edk2
+///
+#define JSON_HAVE_ATOMIC_BUILTINS 0
+
+///
+/// We don't support sync builtins on edk2
+///
+#define JSON_HAVE_SYNC_BUILTINS 0
+
+///
+/// Mzximum deepth is set to 2048
+///
+#define JSON_PARSER_MAX_DEPTH 2048
+
+#endif
diff --git a/RedfishPkg/Library/JsonLib/jansson_private_config.h b/RedfishPkg/Library/JsonLib/jansson_private_config.h
new file mode 100644
index 0000000000..268f91ef8a
--- /dev/null
+++ b/RedfishPkg/Library/JsonLib/jansson_private_config.h
@@ -0,0 +1,19 @@
+/** @file
+ Jansson private configurations for UEFI support.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef JANSSON_PRIVATE_CONFIG_H_
+#define JANSSON_PRIVATE_CONFIG_H_
+
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+
+#define INITIAL_HASHTABLE_ORDER 3
+
+#endif
diff --git a/RedfishPkg/Library/JsonLib/JsonLib.c b/RedfishPkg/Library/JsonLib/JsonLib.c
new file mode 100644
index 0000000000..34ff381aee
--- /dev/null
+++ b/RedfishPkg/Library/JsonLib/JsonLib.c
@@ -0,0 +1,957 @@
+/** @file
+ APIs for JSON operations. The fuctions provided by this library are the
+ wrapper to native open source jansson library. See below document for
+ the API reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html
+
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/JsonLib.h>
+#include <Library/BaseUcs2Utf8Lib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "jansson.h"
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON array,
+ or NULL on error. Initially, the array is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitArray (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_array();
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON object,
+ or NULL on error. Initially, the object is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitObject (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_object();
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input string must be NULL terminated Ascii format, non-Ascii characters will
+ be processed as an error. Unicode characters can also be represented by Ascii string
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Ascii string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitAsciiString (
+ IN CONST CHAR8 *String
+ )
+{
+ UINTN Index;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ while (*(String + Index) != '\0') {
+ if (((*(String + Index)) & 0x80) != 0x00) {
+ return NULL;
+ }
+
+ Index++;
+ }
+
+ return (EDKII_JSON_VALUE)json_string (String);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input must be a NULL terminated UCS2 format Unicode string.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Unicode string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitUnicodeString (
+ IN CHAR16 *String
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Utf8Str;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ Utf8Str = NULL;
+ Status = UCS2StrToUTF8 (String, &Utf8Str);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_VALUE)json_string (Utf8Str);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON integer,
+ or NULL on error.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] Value The integer to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON number or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNumber (
+ IN INT64 Value
+ )
+{
+ return (EDKII_JSON_VALUE)json_integer (Value);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON boolean,
+ or NULL on error.
+
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.
+
+ @param[in] Value The boolean value to initialize.
+
+ @retval The created JSON value which contains a JSON boolean or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitBoolean (
+ IN BOOLEAN Value
+ )
+{
+ return (EDKII_JSON_VALUE)json_boolean (Value);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON NULL,
+ or NULL on error.
+
+ NULL JSON value is kept as static value, and no need to do any cleanup work.
+
+ @retval The created NULL JSON value.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNull (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_null();
+}
+
+/**
+ The function is used to decrease the reference count of a JSON value by one, and once
+ this reference count drops to zero, the value is destroyed and it can no longer be used.
+ If this destroyed value is object type or array type, reference counts for all containing
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed
+ since they are static values kept in memory.
+
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a
+ value is kept for use, its reference count is incremented, and when the value is no longer
+ needed, the reference count is decremented. When the reference count drops to zero, there are
+ no references left, and the value can be destroyed.
+
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message
+ to inform caller the NULL value is passed in.
+
+ @param[in] Json The JSON value to be freed. json_decref may return without any
+ changes if Json is NULL.
+
+**/
+VOID
+EFIAPI
+JsonValueFree (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ json_decref((json_t *)Json);
+}
+
+/**
+ The function is used to create a fresh copy of a JSON value, and all child values are deep
+ copied in a recursive fashion. It should be called when this JSON value might be modified
+ in later use, but the original still wants to be used in somewhere else.
+
+ Reference counts of the returned root JSON value and all child values will be set to 1, and
+ caller needs to cleanup the root value by calling JsonValueFree().
+
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some
+ performance issues, user should avoid unnecessary calls to this function unless it is really
+ needed.
+
+ @param[in] Json The JSON value to be cloned.
+
+ @retval Return the cloned JSON value, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueClone (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return (EDKII_JSON_VALUE)json_deep_copy ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON array.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON array.
+ @retval FALSE The JSON value doesn't contain a JSON array.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsArray (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_array ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON object.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON object.
+ @retval FALSE The JSON value doesn't contain a JSON object.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsObject (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_object ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON Value contains a string, Ascii or
+ Unicode format is not differentiated.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON string.
+ @retval FALSE The JSON value doesn't contain a JSON string.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_string ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON number.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value is contains JSON number.
+ @retval FALSE The JSON value doesn't contain a JSON number.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNumber (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_integer ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON boolean.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON boolean.
+ @retval FALSE The JSON value doesn't contain a JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsBoolean (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_boolean ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON NULL.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON NULL.
+ @retval FALSE The JSON value doesn't contain a JSON NULL.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNull (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_null ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated array in an array type JSON value.
+
+ Any changes to the returned array will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated array in JSON value or NULL.
+
+**/
+EDKII_JSON_ARRAY
+EFIAPI
+JsonValueGetArray (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (Json == NULL || !JsonValueIsArray (Json)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_ARRAY)Json;
+}
+
+/**
+ The function is used to retrieve the associated object in an object type JSON value.
+
+ Any changes to the returned object will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated object in JSON value or NULL.
+
+**/
+EDKII_JSON_OBJECT
+EFIAPI
+JsonValueGetObject (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (Json == NULL || !JsonValueIsObject (Json)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_OBJECT)Json;
+}
+
+/**
+ The function is used to retrieve the associated Ascii string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL.
+
+**/
+CONST CHAR8 *
+EFIAPI
+JsonValueGetAsciiString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ CHAR8 *AsciiStr;
+ UINTN Index;
+
+ AsciiStr = (CHAR8 *) ((json_t *) Json);
+ if (AsciiStr == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ while (*(AsciiStr + Index) != '\0') {
+ if (((*(AsciiStr + Index)) & 0x80) != 0x00) {
+ return NULL;
+ }
+
+ Index++;
+ }
+
+ return AsciiStr;
+}
+
+/**
+ The function is used to retrieve the associated Unicode string in a string type JSON value.
+
+ Caller can do any changes to the returned string without any impact to the original JSON
+ value, and caller needs to free the returned string using FreePool().
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Unicode string in JSON value or NULL.
+
+**/
+CHAR16*
+EFIAPI
+JsonValueGetUnicodeString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR8 *Utf8Str;
+ CHAR16 *Ucs2Str;
+
+ Utf8Str = json_string_value ((json_t *) Json);
+ if (Utf8Str == NULL) {
+ return NULL;
+ }
+
+ Status = UTF8StrToUCS2 ((CHAR8*)Utf8Str, &Ucs2Str);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return Ucs2Str;
+}
+
+/**
+ The function is used to retrieve the associated integer in a number type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will
+ ASSERT() and return 0.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated number in JSON value.
+
+**/
+INT64
+EFIAPI
+JsonValueGetNumber (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ ASSERT (Json != NULL && JsonValueIsNumber (Json));
+ if (Json == NULL || !JsonValueIsNumber (Json)) {
+ return 0;
+ }
+
+ return json_integer_value ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated boolean in a boolean type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will
+ ASSERT() and return FALSE.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated value of JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueGetBoolean (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ ASSERT (Json != NULL && JsonValueIsBoolean (Json));
+ if (Json == NULL || !JsonValueIsBoolean (Json)) {
+ return FALSE;
+ }
+
+ return json_is_true ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL on errors.
+
+**/
+CONST CHAR8*
+EFIAPI
+JsonValueGetString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_string_value ((const json_t *)Json);
+}
+
+/**
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or
+ not a JSON object.
+
+ @param[in] JsonObject The provided JSON object.
+
+ @retval Return the number of elements in this JSON object or 0.
+
+**/
+UINTN
+EFIAPI
+JsonObjectSize (
+ IN EDKII_JSON_OBJECT JsonObject
+ )
+{
+ return json_object_size ((json_t *) JsonObject);
+}
+
+/**
+ The function is used to enumerate all keys in a JSON object.
+
+ Caller should be responsible to free the returned key array reference using
+ FreePool(). But contained keys are read only and must not be modified or freed.
+
+ @param[in] JsonObj The provided JSON object for enumeration.
+ @param[out] KeyCount The count of keys in this JSON object.
+
+ @retval Return an array of the enumerated keys in this JSON object or NULL if
+ JsonObj is not an JSON object, key count is zero or on other errors.
+
+**/
+CHAR8**
+JsonObjectGetKeys (
+ IN EDKII_JSON_OBJECT JsonObj,
+ OUT UINTN *KeyCount
+ )
+{
+
+ UINTN Index;
+ CONST CHAR8 **KeyArray;
+ CONST CHAR8 *Key;
+ EDKII_JSON_VALUE Value;
+
+ if (JsonObj == NULL || KeyCount == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ json_object_foreach(JsonObj, Key, Value) {
+ Index++;
+ }
+ if (Index == 0) {
+ *KeyCount = 0;
+ return NULL;
+ }
+
+ *KeyCount = Index;
+ KeyArray = (CONST CHAR8 **) AllocateZeroPool (*KeyCount * sizeof (CHAR8 *));
+ if (KeyArray == NULL) {
+ return NULL;
+ }
+
+ Key = NULL;
+ Value = NULL;
+ Index = 0;
+ json_object_foreach((json_t *) JsonObj, Key, Value) {
+ KeyArray[Index] = Key;
+ Index++;
+ }
+
+ return (CHAR8 **)KeyArray;
+}
+
+/**
+ The function is used to get a JSON value corresponding to the input key from a JSON object.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when
+ Key-Value is not found in this JSON object.
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be retrieved.
+
+ @retval Return the corresponding JSON value to key, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectGetValue (
+ IN CONST EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key
+ )
+{
+ return (EDKII_JSON_VALUE)json_object_get ((const json_t *)JsonObj, (const char *)Key);
+}
+
+/**
+ The function is used to set a JSON value corresponding to the input key from a JSON object,
+ and the reference count of this value will be increased by 1.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed
+ from this object and thus its' reference count will be decreased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be set.
+ @param[in] Json The JSON value to set to this JSON object mapped by key.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonObjectSetValue (
+ IN EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key,
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (json_object_set ((json_t *) JsonObj, Key, (json_t *) Json) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray
+ is NULL or not a JSON array.
+
+ @param[in] JsonArray The provided JSON array.
+
+ @retval Return the number of elements in this JSON array or 0.
+
+**/
+UINTN
+EFIAPI
+JsonArrayCount (
+ IN EDKII_JSON_ARRAY JsonArray
+ )
+{
+ return json_array_size ((json_t *) JsonArray);
+}
+
+/**
+ The function is used to return the JSON value in the array at position index. The valid range
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.
+
+ @param[in] JsonArray The provided JSON Array.
+
+ @retval Return the JSON value located in the Index position or
+ NULL if JsonArray is not an array or no items in the array.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonArrayGetValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ )
+{
+ return (EDKII_JSON_VALUE)json_array_get ((json_t *) JsonArray, Index);
+}
+
+/**
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of
+ array by 1. The reference count of this value will be increased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON object.
+ @param[in] Json The JSON value to append.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayAppendValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (json_array_append ((json_t *) JsonArray, (json_t *) Json) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ The function is used to remove a JSON value at position index, shifting the elements after index
+ one position towards the start of the array. The reference count of this value will be decreased
+ by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON array.
+ @param[in] Index The Index position before removement.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON array has been removed at position index.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayRemoveValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ )
+{
+ if (json_array_remove ((json_t *) JsonArray, Index) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ Dump JSON to a buffer.
+
+ @param[in] JsonValue The provided JSON value.
+ @param[in] Flags The Index position before removement. The value
+ could be the combination of below flags.
+ - EDKII_JSON_INDENT(n)
+ - EDKII_JSON_COMPACT
+ - EDKII_JSON_ENSURE_ASCII
+ - EDKII_JSON_SORT_KEYS
+ - EDKII_JSON_PRESERVE_ORDER
+ - EDKII_JSON_ENCODE_ANY
+ - EDKII_JSON_ESCAPE_SLASH
+ - EDKII_JSON_REAL_PRECISION(n)
+ - EDKII_JSON_EMBED
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer
+ contain JSON paylaod in ASCII string. The return
+ value must be freed by the caller using FreePool().
+**/
+CHAR8 *
+EFIAPI
+JsonDumpString (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN UINTN Flags
+ )
+{
+ if (JsonValue == NULL) {
+ return NULL;
+ }
+ return json_dumps((json_t *)JsonValue, Flags);
+}
+
+/**
+ Load JSON from a buffer.
+
+ @param[in] Buffer Bufffer to the JSON payload
+ @param[in] BufferLen Length of the buffer
+ @param[in] Flags Flag of loading JSON buffer, the value
+ could be the combination of below flags.
+ - EDKII_JSON_REJECT_DUPLICATES
+ - EDKII_JSON_DISABLE_EOF_CHECK
+ - EDKII_JSON_DECODE_ANY
+ - EDKII_JSON_DECODE_INT_AS_REAL
+ - EDKII_JSON_ALLOW_NUL
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure
+
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadBuffer (
+ IN CONST CHAR8 *Buffer,
+ IN UINTN BufferLen,
+ IN UINTN Flags,
+ IN OUT EDKII_JSON_ERROR *Error
+ )
+{
+ return json_loadb(Buffer, BufferLen, Flags, (json_error_t *)Error);
+}
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ when the value is no longer needed, the reference count is decremented.
+ When the reference count drops to zero, there are no references left and the
+ value can be destroyed.
+
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as
+ a call to json_decref() drops the reference count to zero, the value is
+ destroyed and it can no longer be used.
+
+ @param[in] JsonValue JSON value
+**/
+VOID
+EFIAPI
+JsonDecreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ json_decref (JsonValue);
+}
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),
+ its reference count is incremented.
+
+ This function increment the reference count of json if it's not NULL.
+ Returns EDKII_JSON_VALUE.
+
+ @param[in] JsonValue JSON value
+ @retval EDKII_JSON_VALUE of itself
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonIncreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return json_incref (JsonValue);
+}
+
+/**
+ Returns an opaque iterator which can be used to iterate over all key-value pairs
+ in object, or NULL if object is empty.
+
+ @param[in] JsonValue JSON value
+ @retval Iterator pointer
+**/
+VOID *
+EFIAPI
+JsonObjectIterator (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return json_object_iter (JsonValue);
+}
+
+/**
+ Extract the associated value from iterator.
+
+ @param[in] Iterator Iterator pointer
+ @retval EDKII_JSON_VALUE
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectIteratorValue (
+ IN VOID *Iterator
+ )
+{
+ return json_object_iter_value(Iterator);
+}
+
+/**
+ Returns an iterator pointing to the next key-value pair in object after iter,
+ or NULL if the whole object has been iterated through.
+
+ @param[in] JsonValue JSON value
+ @param[in] Iterator Iterator pointer
+ @retval Iterator pointer
+**/
+VOID *
+JsonObjectIteratorNext (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN VOID *Iterator
+ )
+{
+ return json_object_iter_next(JsonValue, Iterator);
+}
+
+/**
+ Returns the json type of this json value.
+
+ @param[in] JsonValue JSON value
+ @retval JSON type returned
+**/
+EDKII_JSON_TYPE
+EFIAPI
+JsonGetType (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return ((json_t *)JsonValue)->type;
+}
diff --git a/RedfishPkg/Library/JsonLib/load.c b/RedfishPkg/Library/JsonLib/load.c
new file mode 100644
index 0000000000..37e0ba4271
--- /dev/null
+++ b/RedfishPkg/Library/JsonLib/load.c
@@ -0,0 +1,1111 @@
+/*
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent AND MIT
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "jansson_private.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "jansson.h"
+#include "strbuffer.h"
+#include "utf.h"
+
+#define STREAM_STATE_OK 0
+#define STREAM_STATE_EOF -1
+#define STREAM_STATE_ERROR -2
+
+#define TOKEN_INVALID -1
+#define TOKEN_EOF 0
+#define TOKEN_STRING 256
+#define TOKEN_INTEGER 257
+#define TOKEN_REAL 258
+#define TOKEN_TRUE 259
+#define TOKEN_FALSE 260
+#define TOKEN_NULL 261
+
+/* Locale independent versions of isxxx() functions */
+#define l_isupper(c) ('A' <= (c) && (c) <= 'Z')
+#define l_islower(c) ('a' <= (c) && (c) <= 'z')
+#define l_isalpha(c) (l_isupper(c) || l_islower(c))
+#define l_isdigit(c) ('0' <= (c) && (c) <= '9')
+#define l_isxdigit(c) \
+ (l_isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f'))
+
+/* Read one byte from stream, convert to unsigned char, then int, and
+ return. return EOF on end of file. This corresponds to the
+ behaviour of fgetc(). */
+typedef int (*get_func)(void *data);
+
+typedef struct {
+ get_func get;
+ void *data;
+ char buffer[5];
+ size_t buffer_pos;
+ int state;
+ int line;
+ int column, last_column;
+ size_t position;
+} stream_t;
+
+typedef struct {
+ stream_t stream;
+ strbuffer_t saved_text;
+ size_t flags;
+ size_t depth;
+ int token;
+ union {
+ struct {
+ char *val;
+ size_t len;
+ } string;
+ json_int_t integer;
+ double real;
+ } value;
+} lex_t;
+
+#define stream_to_lex(stream) container_of(stream, lex_t, stream)
+
+/*** error reporting ***/
+
+static void error_set(json_error_t *error, const lex_t *lex, enum json_error_code code,
+ const char *msg, ...) {
+ va_list ap;
+ char msg_text[JSON_ERROR_TEXT_LENGTH];
+ char msg_with_context[JSON_ERROR_TEXT_LENGTH];
+
+ int line = -1, col = -1;
+ size_t pos = 0;
+ const char *result = msg_text;
+
+ if (!error)
+ return;
+
+ va_start(ap, msg);
+ vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap);
+ msg_text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ va_end(ap);
+
+ if (lex) {
+ const char *saved_text = strbuffer_value(&lex->saved_text);
+
+ line = lex->stream.line;
+ col = lex->stream.column;
+ pos = lex->stream.position;
+
+ if (saved_text && saved_text[0]) {
+ if (lex->saved_text.length <= 20) {
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'",
+ msg_text, saved_text);
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ result = msg_with_context;
+ }
+ } else {
+ if (code == json_error_invalid_syntax) {
+ /* More specific error code for premature end of file. */
+ code = json_error_premature_end_of_input;
+ }
+ if (lex->stream.state == STREAM_STATE_ERROR) {
+ /* No context for UTF-8 decoding errors */
+ result = msg_text;
+ } else {
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file",
+ msg_text);
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ result = msg_with_context;
+ }
+ }
+ }
+
+ jsonp_error_set(error, line, col, pos, code, "%s", result);
+}
+
+/*** lexical analyzer ***/
+
+static void stream_init(stream_t *stream, get_func get, void *data) {
+ stream->get = get;
+ stream->data = data;
+ stream->buffer[0] = '\0';
+ stream->buffer_pos = 0;
+
+ stream->state = STREAM_STATE_OK;
+ stream->line = 1;
+ stream->column = 0;
+ stream->position = 0;
+}
+
+static int stream_get(stream_t *stream, json_error_t *error) {
+ int c;
+
+ if (stream->state != STREAM_STATE_OK)
+ return stream->state;
+
+ if (!stream->buffer[stream->buffer_pos]) {
+ c = stream->get(stream->data);
+ if (c == EOF) {
+ stream->state = STREAM_STATE_EOF;
+ return STREAM_STATE_EOF;
+ }
+
+ stream->buffer[0] = c;
+ stream->buffer_pos = 0;
+
+ if (0x80 <= c && c <= 0xFF) {
+ /* multi-byte UTF-8 sequence */
+ size_t i, count;
+
+ count = utf8_check_first(c);
+ if (!count)
+ goto out;
+
+ assert(count >= 2);
+
+ for (i = 1; i < count; i++)
+ stream->buffer[i] = stream->get(stream->data);
+
+ if (!utf8_check_full(stream->buffer, count, NULL))
+ goto out;
+
+ stream->buffer[count] = '\0';
+ } else
+ stream->buffer[1] = '\0';
+ }
+
+ c = stream->buffer[stream->buffer_pos++];
+
+ stream->position++;
+ if (c == '\n') {
+ stream->line++;
+ stream->last_column = stream->column;
+ stream->column = 0;
+ } else if (utf8_check_first(c)) {
+ /* track the Unicode character column, so increment only if
+ this is the first character of a UTF-8 sequence */
+ stream->column++;
+ }
+
+ return c;
+
+out:
+ stream->state = STREAM_STATE_ERROR;
+ error_set(error, stream_to_lex(stream), json_error_invalid_utf8,
+ "unable to decode byte 0x%x", c);
+ return STREAM_STATE_ERROR;
+}
+
+static void stream_unget(stream_t *stream, int c) {
+ if (c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR)
+ return;
+
+ stream->position--;
+ if (c == '\n') {
+ stream->line--;
+ stream->column = stream->last_column;
+ } else if (utf8_check_first(c))
+ stream->column--;
+
+ assert(stream->buffer_pos > 0);
+ stream->buffer_pos--;
+ assert(stream->buffer[stream->buffer_pos] == c);
+}
+
+static int lex_get(lex_t *lex, json_error_t *error) {
+ return stream_get(&lex->stream, error);
+}
+
+static void lex_save(lex_t *lex, int c) { strbuffer_append_byte(&lex->saved_text, c); }
+
+static int lex_get_save(lex_t *lex, json_error_t *error) {
+ int c = stream_get(&lex->stream, error);
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR)
+ lex_save(lex, c);
+ return c;
+}
+
+static void lex_unget(lex_t *lex, int c) { stream_unget(&lex->stream, c); }
+
+static void lex_unget_unsave(lex_t *lex, int c) {
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {
+/* Since we treat warnings as errors, when assertions are turned
+ * off the "d" variable would be set but never used. Which is
+ * treated as an error by GCC.
+ */
+#ifndef NDEBUG
+ char d;
+#endif
+ stream_unget(&lex->stream, c);
+#ifndef NDEBUG
+ d =
+#endif
+ strbuffer_pop(&lex->saved_text);
+ assert(c == d);
+ }
+}
+
+static void lex_save_cached(lex_t *lex) {
+ while (lex->stream.buffer[lex->stream.buffer_pos] != '\0') {
+ lex_save(lex, lex->stream.buffer[lex->stream.buffer_pos]);
+ lex->stream.buffer_pos++;
+ lex->stream.position++;
+ }
+}
+
+static void lex_free_string(lex_t *lex) {
+ jsonp_free(lex->value.string.val);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+}
+
+/* assumes that str points to 'u' plus at least 4 valid hex digits */
+static int32_t decode_unicode_escape(const char *str) {
+ int i;
+ int32_t value = 0;
+
+ assert(str[0] == 'u');
+
+ for (i = 1; i <= 4; i++) {
+ char c = str[i];
+ value <<= 4;
+ if (l_isdigit(c))
+ value += c - '0';
+ else if (l_islower(c))
+ value += c - 'a' + 10;
+ else if (l_isupper(c))
+ value += c - 'A' + 10;
+ else
+ return -1;
+ }
+
+ return value;
+}
+
+static void lex_scan_string(lex_t *lex, json_error_t *error) {
+ int c;
+ const char *p;
+ char *t;
+ int i;
+
+ lex->value.string.val = NULL;
+ lex->token = TOKEN_INVALID;
+
+ c = lex_get_save(lex, error);
+
+ while (c != '"') {
+ if (c == STREAM_STATE_ERROR)
+ goto out;
+
+ else if (c == STREAM_STATE_EOF) {
+ error_set(error, lex, json_error_premature_end_of_input,
+ "premature end of input");
+ goto out;
+ }
+
+ else if (0 <= c && c <= 0x1F) {
+ /* control character */
+ lex_unget_unsave(lex, c);
+ if (c == '\n')
+ error_set(error, lex, json_error_invalid_syntax, "unexpected newline");
+ else
+ error_set(error, lex, json_error_invalid_syntax, "control character 0x%x",
+ c);
+ goto out;
+ }
+
+ else if (c == '\\') {
+ c = lex_get_save(lex, error);
+ if (c == 'u') {
+ c = lex_get_save(lex, error);
+ for (i = 0; i < 4; i++) {
+ if (!l_isxdigit(c)) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid escape");
+ goto out;
+ }
+ c = lex_get_save(lex, error);
+ }
+ } else if (c == '"' || c == '\\' || c == '/' || c == 'b' || c == 'f' ||
+ c == 'n' || c == 'r' || c == 't')
+ c = lex_get_save(lex, error);
+ else {
+ error_set(error, lex, json_error_invalid_syntax, "invalid escape");
+ goto out;
+ }
+ } else
+ c = lex_get_save(lex, error);
+ }
+
+ /* the actual value is at most of the same length as the source
+ string, because:
+ - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte
+ - a single \uXXXX escape (length 6) is converted to at most 3 bytes
+ - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
+ are converted to 4 bytes
+ */
+ t = jsonp_malloc(lex->saved_text.length + 1);
+ if (!t) {
+ /* this is not very nice, since TOKEN_INVALID is returned */
+ goto out;
+ }
+ lex->value.string.val = t;
+
+ /* + 1 to skip the " */
+ p = strbuffer_value(&lex->saved_text) + 1;
+
+ while (*p != '"') {
+ if (*p == '\\') {
+ p++;
+ if (*p == 'u') {
+ size_t length;
+ int32_t value;
+
+ value = decode_unicode_escape(p);
+ if (value < 0) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
+ p += 5;
+
+ if (0xD800 <= value && value <= 0xDBFF) {
+ /* surrogate pair */
+ if (*p == '\\' && *(p + 1) == 'u') {
+ int32_t value2 = decode_unicode_escape(++p);
+ if (value2 < 0) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
+ p += 5;
+
+ if (0xDC00 <= value2 && value2 <= 0xDFFF) {
+ /* valid second surrogate */
+ value =
+ ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x10000;
+ } else {
+ /* invalid second surrogate */
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X\\u%04X'", value, value2);
+ goto out;
+ }
+ } else {
+ /* no second surrogate */
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X'", value);
+ goto out;
+ }
+ } else if (0xDC00 <= value && value <= 0xDFFF) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X'", value);
+ goto out;
+ }
+
+ if (utf8_encode(value, t, &length))
+ assert(0);
+ t += length;
+ } else {
+ switch (*p) {
+ case '"':
+ case '\\':
+ case '/':
+ *t = *p;
+ break;
+ case 'b':
+ *t = '\b';
+ break;
+ case 'f':
+ *t = '\f';
+ break;
+ case 'n':
+ *t = '\n';
+ break;
+ case 'r':
+ *t = '\r';
+ break;
+ case 't':
+ *t = '\t';
+ break;
+ default:
+ assert(0);
+ }
+ t++;
+ p++;
+ }
+ } else
+ *(t++) = *(p++);
+ }
+ *t = '\0';
+ lex->value.string.len = t - lex->value.string.val;
+ lex->token = TOKEN_STRING;
+ return;
+
+out:
+ lex_free_string(lex);
+}
+
+#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
+#if JSON_INTEGER_IS_LONG_LONG
+#ifdef _MSC_VER /* Microsoft Visual Studio */
+#define json_strtoint _strtoi64
+#else
+#define json_strtoint strtoll
+#endif
+#else
+#define json_strtoint strtol
+#endif
+#endif
+
+static int lex_scan_number(lex_t *lex, int c, json_error_t *error) {
+ const char *saved_text;
+ char *end;
+ double doubleval;
+
+ lex->token = TOKEN_INVALID;
+
+ if (c == '-')
+ c = lex_get_save(lex, error);
+
+ if (c == '0') {
+ c = lex_get_save(lex, error);
+ if (l_isdigit(c)) {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+ } else if (l_isdigit(c)) {
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ } else {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+
+ if (!(lex->flags & JSON_DECODE_INT_AS_REAL) && c != '.' && c != 'E' && c != 'e') {
+ json_int_t intval;
+
+ lex_unget_unsave(lex, c);
+
+ saved_text = strbuffer_value(&lex->saved_text);
+
+ errno = 0;
+ intval = json_strtoint(saved_text, &end, 10);
+ if (errno == ERANGE) {
+ if (intval < 0)
+ error_set(error, lex, json_error_numeric_overflow,
+ "too big negative integer");
+ else
+ error_set(error, lex, json_error_numeric_overflow, "too big integer");
+ goto out;
+ }
+
+ assert(end == saved_text + lex->saved_text.length);
+
+ lex->token = TOKEN_INTEGER;
+ lex->value.integer = intval;
+ return 0;
+ }
+
+ if (c == '.') {
+ c = lex_get(lex, error);
+ if (!l_isdigit(c)) {
+ lex_unget(lex, c);
+ goto out;
+ }
+ lex_save(lex, c);
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ }
+
+ if (c == 'E' || c == 'e') {
+ c = lex_get_save(lex, error);
+ if (c == '+' || c == '-')
+ c = lex_get_save(lex, error);
+
+ if (!l_isdigit(c)) {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ }
+
+ lex_unget_unsave(lex, c);
+
+ if (jsonp_strtod(&lex->saved_text, &doubleval)) {
+ error_set(error, lex, json_error_numeric_overflow, "real number overflow");
+ goto out;
+ }
+
+ lex->token = TOKEN_REAL;
+ lex->value.real = doubleval;
+ return 0;
+
+out:
+ return -1;
+}
+
+static int lex_scan(lex_t *lex, json_error_t *error) {
+ int c;
+
+ strbuffer_clear(&lex->saved_text);
+
+ if (lex->token == TOKEN_STRING)
+ lex_free_string(lex);
+
+ do
+ c = lex_get(lex, error);
+ while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+
+ if (c == STREAM_STATE_EOF) {
+ lex->token = TOKEN_EOF;
+ goto out;
+ }
+
+ if (c == STREAM_STATE_ERROR) {
+ lex->token = TOKEN_INVALID;
+ goto out;
+ }
+
+ lex_save(lex, c);
+
+ if (c == '{' || c == '}' || c == '[' || c == ']' || c == ':' || c == ',')
+ lex->token = c;
+
+ else if (c == '"')
+ lex_scan_string(lex, error);
+
+ else if (l_isdigit(c) || c == '-') {
+ if (lex_scan_number(lex, c, error))
+ goto out;
+ }
+
+ else if (l_isalpha(c)) {
+ /* eat up the whole identifier for clearer error messages */
+ const char *saved_text;
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isalpha(c));
+ lex_unget_unsave(lex, c);
+
+ saved_text = strbuffer_value(&lex->saved_text);
+
+ if (strcmp(saved_text, "true") == 0)
+ lex->token = TOKEN_TRUE;
+ else if (strcmp(saved_text, "false") == 0)
+ lex->token = TOKEN_FALSE;
+ else if (strcmp(saved_text, "null") == 0)
+ lex->token = TOKEN_NULL;
+ else
+ lex->token = TOKEN_INVALID;
+ }
+
+ else {
+ /* save the rest of the input UTF-8 sequence to get an error
+ message of valid UTF-8 */
+ lex_save_cached(lex);
+ lex->token = TOKEN_INVALID;
+ }
+
+out:
+ return lex->token;
+}
+
+static char *lex_steal_string(lex_t *lex, size_t *out_len) {
+ char *result = NULL;
+ if (lex->token == TOKEN_STRING) {
+ result = lex->value.string.val;
+ *out_len = lex->value.string.len;
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ }
+ return result;
+}
+
+static int lex_init(lex_t *lex, get_func get, size_t flags, void *data) {
+ stream_init(&lex->stream, get, data);
+ if (strbuffer_init(&lex->saved_text))
+ return -1;
+
+ lex->flags = flags;
+ lex->token = TOKEN_INVALID;
+ return 0;
+}
+
+static void lex_close(lex_t *lex) {
+ if (lex->token == TOKEN_STRING)
+ lex_free_string(lex);
+ strbuffer_close(&lex->saved_text);
+}
+
+/*** parser ***/
+
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error);
+
+static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *object = json_object();
+ if (!object)
+ return NULL;
+
+ lex_scan(lex, error);
+ if (lex->token == '}')
+ return object;
+
+ while (1) {
+ char *key;
+ size_t len;
+ json_t *value;
+
+ if (lex->token != TOKEN_STRING) {
+ error_set(error, lex, json_error_invalid_syntax, "string or '}' expected");
+ goto error;
+ }
+
+ key = lex_steal_string(lex, &len);
+ if (!key)
+ return NULL;
+ if (memchr(key, '\0', len)) {
+ jsonp_free(key);
+ error_set(error, lex, json_error_null_byte_in_key,
+ "NUL byte in object key not supported");
+ goto error;
+ }
+
+ if (flags & JSON_REJECT_DUPLICATES) {
+ if (json_object_get(object, key)) {
+ jsonp_free(key);
+ error_set(error, lex, json_error_duplicate_key, "duplicate object key");
+ goto error;
+ }
+ }
+
+ lex_scan(lex, error);
+ if (lex->token != ':') {
+ jsonp_free(key);
+ error_set(error, lex, json_error_invalid_syntax, "':' expected");
+ goto error;
+ }
+
+ lex_scan(lex, error);
+ value = parse_value(lex, flags, error);
+ if (!value) {
+ jsonp_free(key);
+ goto error;
+ }
+
+ if (json_object_set_new_nocheck(object, key, value)) {
+ jsonp_free(key);
+ goto error;
+ }
+
+ jsonp_free(key);
+
+ lex_scan(lex, error);
+ if (lex->token != ',')
+ break;
+
+ lex_scan(lex, error);
+ }
+
+ if (lex->token != '}') {
+ error_set(error, lex, json_error_invalid_syntax, "'}' expected");
+ goto error;
+ }
+
+ return object;
+
+error:
+ json_decref(object);
+ return NULL;
+}
+
+static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *array = json_array();
+ if (!array)
+ return NULL;
+
+ lex_scan(lex, error);
+ if (lex->token == ']')
+ return array;
+
+ while (lex->token) {
+ json_t *elem = parse_value(lex, flags, error);
+ if (!elem)
+ goto error;
+
+ if (json_array_append_new(array, elem)) {
+ goto error;
+ }
+
+ lex_scan(lex, error);
+ if (lex->token != ',')
+ break;
+
+ lex_scan(lex, error);
+ }
+
+ if (lex->token != ']') {
+ error_set(error, lex, json_error_invalid_syntax, "']' expected");
+ goto error;
+ }
+
+ return array;
+
+error:
+ json_decref(array);
+ return NULL;
+}
+
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *json;
+
+ lex->depth++;
+ if (lex->depth > JSON_PARSER_MAX_DEPTH) {
+ error_set(error, lex, json_error_stack_overflow, "maximum parsing depth reached");
+ return NULL;
+ }
+
+ switch (lex->token) {
+ case TOKEN_STRING: {
+ const char *value = lex->value.string.val;
+ size_t len = lex->value.string.len;
+
+ if (!(flags & JSON_ALLOW_NUL)) {
+ if (memchr(value, '\0', len)) {
+ error_set(error, lex, json_error_null_character,
+ "\\u0000 is not allowed without JSON_ALLOW_NUL");
+ return NULL;
+ }
+ }
+
+ json = jsonp_stringn_nocheck_own(value, len);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ break;
+ }
+
+ case TOKEN_INTEGER: {
+ json = json_integer(lex->value.integer);
+ break;
+ }
+
+ case TOKEN_REAL: {
+ json = json_real(lex->value.real);
+ break;
+ }
+
+ case TOKEN_TRUE:
+ json = json_true();
+ break;
+
+ case TOKEN_FALSE:
+ json = json_false();
+ break;
+
+ case TOKEN_NULL:
+ json = json_null();
+ break;
+
+ case '{':
+ json = parse_object(lex, flags, error);
+ break;
+
+ case '[':
+ json = parse_array(lex, flags, error);
+ break;
+
+ case TOKEN_INVALID:
+ error_set(error, lex, json_error_invalid_syntax, "invalid token");
+ return NULL;
+
+ default:
+ error_set(error, lex, json_error_invalid_syntax, "unexpected token");
+ return NULL;
+ }
+
+ if (!json)
+ return NULL;
+
+ lex->depth--;
+ return json;
+}
+
+static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *result;
+
+ lex->depth = 0;
+
+ lex_scan(lex, error);
+ if (!(flags & JSON_DECODE_ANY)) {
+ if (lex->token != '[' && lex->token != '{') {
+ error_set(error, lex, json_error_invalid_syntax, "'[' or '{' expected");
+ return NULL;
+ }
+ }
+
+ result = parse_value(lex, flags, error);
+ if (!result)
+ return NULL;
+
+ if (!(flags & JSON_DISABLE_EOF_CHECK)) {
+ lex_scan(lex, error);
+ if (lex->token != TOKEN_EOF) {
+ error_set(error, lex, json_error_end_of_input_expected,
+ "end of file expected");
+ json_decref(result);
+ return NULL;
+ }
+ }
+
+ if (error) {
+ /* Save the position even though there was no error */
+ error->position = (int)lex->stream.position;
+ }
+
+ return result;
+}
+
+typedef struct {
+ const char *data;
+ size_t pos;
+} string_data_t;
+
+static int string_get(void *data) {
+ char c;
+ string_data_t *stream = (string_data_t *)data;
+ c = stream->data[stream->pos];
+ if (c == '\0')
+ return EOF;
+ else {
+ stream->pos++;
+ return (unsigned char)c;
+ }
+}
+
+json_t *json_loads(const char *string, size_t flags, json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+ string_data_t stream_data;
+
+ jsonp_error_init(error, "<string>");
+
+ if (string == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ stream_data.data = string;
+ stream_data.pos = 0;
+
+ if (lex_init(&lex, string_get, flags, (void *)&stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+typedef struct {
+ const char *data;
+ size_t len;
+ size_t pos;
+} buffer_data_t;
+
+static int buffer_get(void *data) {
+ char c;
+ buffer_data_t *stream = data;
+ if (stream->pos >= stream->len)
+ return EOF;
+
+ c = stream->data[stream->pos];
+ stream->pos++;
+ return (unsigned char)c;
+}
+
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+ buffer_data_t stream_data;
+
+ jsonp_error_init(error, "<buffer>");
+
+ if (buffer == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ stream_data.data = buffer;
+ stream_data.pos = 0;
+ stream_data.len = buflen;
+
+ if (lex_init(&lex, buffer_get, flags, (void *)&stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) {
+ lex_t lex;
+ const char *source;
+ json_t *result;
+#ifdef HAVE_UNISTD_H
+ if (input == stdin)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)fgetc, flags, input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+static int fd_get_func(int *fd) {
+#ifdef HAVE_UNISTD_H
+ uint8_t c;
+ if (read(*fd, &c, 1) == 1)
+ return c;
+#endif
+ return EOF;
+}
+
+json_t *json_loadfd(int input, size_t flags, json_error_t *error) {
+ lex_t lex;
+ const char *source;
+ json_t *result;
+
+#ifdef HAVE_UNISTD_H
+ if (input == STDIN_FILENO)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input < 0) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)fd_get_func, flags, &input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error) {
+ json_t *result;
+ FILE *fp;
+
+ jsonp_error_init(error, path);
+
+ if (path == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ fp = fopen(path, "rb");
+ if (!fp) {
+ error_set(error, NULL, json_error_cannot_open_file, "unable to open %s: %s", path,
+ strerror(errno));
+ return NULL;
+ }
+
+ result = json_loadf(fp, flags, error);
+
+ fclose(fp);
+ return result;
+}
+
+#define MAX_BUF_LEN 1024
+
+typedef struct {
+ char data[MAX_BUF_LEN];
+ size_t len;
+ size_t pos;
+ json_load_callback_t callback;
+ void *arg;
+} callback_data_t;
+
+static int callback_get(void *data) {
+ char c;
+ callback_data_t *stream = data;
+
+ if (stream->pos >= stream->len) {
+ stream->pos = 0;
+ stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg);
+ if (stream->len == 0 || stream->len == (size_t)-1)
+ return EOF;
+ }
+
+ c = stream->data[stream->pos];
+ stream->pos++;
+ return (unsigned char)c;
+}
+
+json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags,
+ json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+
+ callback_data_t stream_data;
+
+ memset(&stream_data, 0, sizeof(stream_data));
+ stream_data.callback = callback;
+ stream_data.arg = arg;
+
+ jsonp_error_init(error, "<callback>");
+
+ if (callback == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)callback_get, flags, &stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
diff --git a/RedfishPkg/Library/JsonLib/Readme.rst b/RedfishPkg/Library/JsonLib/Readme.rst
new file mode 100644
index 0000000000..1c652591c7
--- /dev/null
+++ b/RedfishPkg/Library/JsonLib/Readme.rst
@@ -0,0 +1,35 @@
+=============================================================================
+ Introduction
+=============================================================================
+ Jansson is a C library for encoding, decoding and manipulating JSON data.
+Its main features and design principles are:
+
+ - Simple and intuitive API and data model
+ - Comprehensive documentation
+ - No dependencies on other libraries
+ - Full Unicode support (UTF-8)
+ - Extensive test suite
+
+ Jansson is licensed under the MIT license(refer to ReadMe.rst under edk2).
+It is used in production and its API is stable. It works on numerous
+platforms, including numerous Unix like systems and Windows. It's suitable
+for use on any system, including desktop, server, and small embedded systems.
+
+ In UEFI/EDKII environment, Redfish project consumes jansson to achieve JSON
+operations.
+
+* Jansson version on edk2: 2.13.1, API reference is on the below URL,
+ https://jansson.readthedocs.io/en/2.13/apiref.html
+
+* EDKII jansson library wrapper:
+ - JsonLib.h:
+ This is the denifitions of EDKII JSON APIs which are mapped to
+ jannson funcitons accordingly.
+
+*Known issue:
+ Build fail with jansson/src/load.c, add code in load.c to conditionally
+ use stdin according to HAVE_UNISTD_H macro. The PR is submitted to
+ jansson open source community.
+ https://github.com/akheron/jansson/pull/558
+
+
diff --git a/RedfishPkg/RedfishPkg.ci.yaml b/RedfishPkg/RedfishPkg.ci.yaml
index e410d1a608..fde6fa89bc 100644
--- a/RedfishPkg/RedfishPkg.ci.yaml
+++ b/RedfishPkg/RedfishPkg.ci.yaml
@@ -35,7 +35,13 @@
"PrivateInclude/Crt/string.h",
"PrivateInclude/Crt/time.h",
"PrivateInclude/Library/RedfishCrtLib.h",
- "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c"
+ "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c",
+ ##
+ ## For jansson library open source
+ ## load.c is overrided from open source.
+ "Library/JsonLib/load.c",
+ "Library/JsonLib/jansson_config.h",
+ "Library/JsonLib/jansson_private_config.h"
]
},
"CompilerPlugin": {
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread