]> xenbits.xensource.com Git - ovmf.git/commitdiff
MdePkg: Support FDT library.
authorBenny Lin <benny.lin@intel.com>
Thu, 4 May 2023 23:48:11 +0000 (16:48 -0700)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 5 May 2023 03:45:21 +0000 (03:45 +0000)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4392
Add FDT support in EDK2 by submodule 3rd party libfdt
(https://github.com/devicetree-org/pylibfdt/tree/main/libfdt)
and refer to LibcLib implementation by Pedro.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Benny Lin <benny.lin@intel.com>
Acked-by: Pedro Falcato <pedro.falcato@gmail.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
15 files changed:
MdePkg/Include/Library/FdtLib.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/BaseFdtLib.inf [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/BaseFdtLib.uni [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/FdtLib.c [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/LibFdtSupport.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/LibFdtWrapper.c [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/limits.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/stdbool.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/stddef.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/stdint.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/stdlib.h [new file with mode: 0644]
MdePkg/Library/BaseFdtLib/string.h [new file with mode: 0644]
MdePkg/MdePkg.ci.yaml
MdePkg/MdePkg.dec
MdePkg/MdePkg.dsc

diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h
new file mode 100644 (file)
index 0000000..cf5ceba
--- /dev/null
@@ -0,0 +1,401 @@
+/** @file\r
+  Flattened Device Tree Library.\r
+\r
+  All structure data are in big-endian format.\r
+  Functions are provided for converting data between\r
+  little-endian and big-endian.\r
+  For example:\r
+  Pushing data to FDT blob needs to convert data to\r
+  big-endian by CpuToFdt*().\r
+  Retrieving data from FDT blob needs to convert data to\r
+  little-endian by Fdt*ToCpu().\r
+  Refer to FDT specification: https://www.devicetree.org/specifications/\r
+\r
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef FDT_LIB_H_\r
+#define FDT_LIB_H_\r
+\r
+/**\r
+  Flattened Device Tree definition\r
+\r
+  The Devicetree Blob (DTB) format is a binary encoding with big-endian.\r
+  When producing or consuming the blob data, CpuToFdt*() or Fdt*ToCpu()\r
+  provided by this library may be called to convert data between\r
+  big-endian and little-endian.\r
+**/\r
+typedef struct {\r
+  UINT32    Magic;               /* magic word FDT_MAGIC */\r
+  UINT32    TotalSize;           /* total size of DT block */\r
+  UINT32    OffsetDtStruct;      /* offset to structure */\r
+  UINT32    OffsetDtStrings;     /* offset to strings */\r
+  UINT32    OffsetMemRsvmap;     /* offset to memory reserve map */\r
+  UINT32    Version;             /* format version */\r
+  UINT32    LastCompVersion;     /* last compatible version */\r
+\r
+  /* version 2 fields below */\r
+  UINT32    BootCpuidPhys;       /* Which physical CPU id we're\r
+                                    booting on */\r
+  /* version 3 fields below */\r
+  UINT32    SizeDtStrings;       /* size of the strings block */\r
+\r
+  /* version 17 fields below */\r
+  UINT32    SizeDtStruct;        /* size of the structure block */\r
+} FDT_HEADER;\r
+\r
+typedef struct {\r
+  UINT64    Address;\r
+  UINT64    Size;\r
+} FDT_RESERVE_ENTRY;\r
+\r
+typedef struct {\r
+  UINT32    Tag;\r
+  CHAR8     Name[];\r
+} FDT_NODE_HEADER;\r
+\r
+typedef struct {\r
+  UINT32    Tag;\r
+  UINT32    Length;\r
+  UINT32    NameOffset;\r
+  CHAR8     Data[];\r
+} FDT_PROPERTY;\r
+\r
+/**\r
+  Convert UINT16 data of the FDT blob to little-endian\r
+\r
+  @param[in] Value            The value to the blob data.\r
+\r
+  @return The value to be converted to little-endian.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+Fdt16ToCpu (\r
+  IN UINT16  Value\r
+  );\r
+\r
+/**\r
+  Convert UINT16 data to big-endian for aligned with the FDT blob\r
+\r
+  @param[in] Value            The value to align with the FDT blob.\r
+\r
+  @return The value to be converted to big-endian.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+CpuToFdt16 (\r
+  IN UINT16  Value\r
+  );\r
+\r
+/**\r
+  Convert UINT32 data of the FDT blob to little-endian\r
+\r
+  @param[in] Value            The value to the blob data.\r
+\r
+  @return The value to be converted to little-endian.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+Fdt32ToCpu (\r
+  IN UINT32  Value\r
+  );\r
+\r
+/**\r
+  Convert UINT32 data to big-endian for aligned with the FDT blob\r
+\r
+  @param[in] Value            The value to align with the FDT blob.\r
+\r
+  @return The value to be converted to big-endian.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+CpuToFdt32 (\r
+  IN UINT32  Value\r
+  );\r
+\r
+/**\r
+  Convert UINT64 data of the FDT blob to little-endian\r
+\r
+  @param[in] Value            The value to the blob data.\r
+\r
+  @return The value to be converted to little-endian.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+Fdt64ToCpu (\r
+  IN UINT64  Value\r
+  );\r
+\r
+/**\r
+  Convert UINT64 data to big-endian for aligned with the FDT blob\r
+\r
+  @param[in] Value            The value to align with the FDT blob.\r
+\r
+  @return The value to be converted to big-endian.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+CpuToFdt64 (\r
+  IN UINT64  Value\r
+  );\r
+\r
+/**\r
+  Verify the header of the Flattened Device Tree\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+\r
+  @return Zero for successfully, otherwise failed.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtCheckHeader (\r
+  IN CONST VOID  *Fdt\r
+  );\r
+\r
+/**\r
+  Create a empty Flattened Device Tree.\r
+\r
+  @param[in] Buffer         The pointer to allocate a pool for FDT blob.\r
+  @param[in] BufferSize     The BufferSize to the pool size.\r
+\r
+  @return Zero for successfully, otherwise failed.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtCreateEmptyTree (\r
+  IN VOID    *Buffer,\r
+  IN UINT32  BufferSize\r
+  );\r
+\r
+/**\r
+  Returns a offset of next node from the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous node.\r
+  @param[in] Depth          The depth to the level of tree hierarchy.\r
+\r
+  @return The offset to next node offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNextNode (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset,\r
+  IN INT32       *Depth\r
+  );\r
+\r
+/**\r
+  Returns a offset of first node under the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous node.\r
+\r
+  @return The offset to next node offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtFirstSubnode (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset\r
+  );\r
+\r
+/**\r
+  Returns a offset of next node from the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous node.\r
+\r
+  @return The offset to next node offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNextSubnode (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset\r
+  );\r
+\r
+/**\r
+  Returns a offset of first node which includes the given name.\r
+\r
+  @param[in] Fdt             The pointer to FDT blob.\r
+  @param[in] ParentOffset    The offset to the node which start find under.\r
+  @param[in] Name            The name to search the node with the name.\r
+  @param[in] NameLength      The length of the name to check only.\r
+\r
+  @return The offset to node offset with given node name.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtSubnodeOffsetNameLen (\r
+  IN CONST VOID   *Fdt,\r
+  IN INT32        ParentOffset,\r
+  IN CONST CHAR8  *Name,\r
+  IN INT32        NameLength\r
+  );\r
+\r
+/**\r
+  Returns a offset of first node which includes the given property name and value.\r
+\r
+  @param[in] Fdt             The pointer to FDT blob.\r
+  @param[in] StartOffset     The offset to the starting node to find.\r
+  @param[in] PropertyName    The property name to search the node including the named property.\r
+  @param[in] PropertyValue   The property value (big-endian) to check the same property value.\r
+  @param[in] PropertyLength  The length of the value in PropertValue.\r
+\r
+  @return The offset to node offset with given property.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNodeOffsetByPropValue (\r
+  IN CONST VOID   *Fdt,\r
+  IN INT32        StartOffset,\r
+  IN CONST CHAR8  *PropertyName,\r
+  IN CONST VOID   *PropertyValue,\r
+  IN INT32        PropertyLength\r
+  );\r
+\r
+/**\r
+  Returns a property with the given name from the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] NodeOffset     The offset to the given node.\r
+  @param[in] Name           The name to the property which need be searched\r
+  @param[in] Length         The length to the size of the property found.\r
+\r
+  @return The property to the structure of the found property. Since the data\r
+          come from FDT blob, it's encoding with big-endian.\r
+\r
+**/\r
+CONST FDT_PROPERTY *\r
+EFIAPI\r
+FdtGetProperty (\r
+  IN CONST VOID   *Fdt,\r
+  IN INT32        NodeOffset,\r
+  IN CONST CHAR8  *Name,\r
+  IN INT32        *Length\r
+  );\r
+\r
+/**\r
+  Returns a offset of first property in the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] NodeOffset     The offset to the node which need be searched.\r
+\r
+  @return The offset to first property offset in the given node.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtFirstPropertyOffset (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       NodeOffset\r
+  );\r
+\r
+/**\r
+  Returns a offset of next property from the given property.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous property.\r
+\r
+  @return The offset to next property offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNextPropertyOffset (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset\r
+  );\r
+\r
+/**\r
+  Returns a property from the given offset of the property.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to the given offset of the property.\r
+  @param[in] Length         The length to the size of the property found.\r
+\r
+  @return The property to the structure of the given property offset.\r
+\r
+**/\r
+CONST FDT_PROPERTY *\r
+EFIAPI\r
+FdtGetPropertyByOffset (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset,\r
+  IN INT32       *Length\r
+  );\r
+\r
+/**\r
+  Returns a string by the given string offset.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] StrOffset      The offset to the location in the strings block of FDT.\r
+  @param[in] Length         The length to the size of string which need be retrieved.\r
+\r
+  @return The string to the given string offset.\r
+\r
+**/\r
+CONST CHAR8 *\r
+EFIAPI\r
+FdtGetString (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       StrOffset,\r
+  IN INT32       *Length        OPTIONAL\r
+  );\r
+\r
+/**\r
+  Add a new node to the FDT.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] ParentOffset   The offset to the node offset which want to add in.\r
+  @param[in] Name           The name to name the node.\r
+\r
+  @return  The offset to the new node.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtAddSubnode (\r
+  IN VOID         *Fdt,\r
+  IN INT32        ParentOffset,\r
+  IN CONST CHAR8  *Name\r
+  );\r
+\r
+/**\r
+  Add or modify a property in the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] NodeOffset     The offset to the node offset which want to add in.\r
+  @param[in] Name           The name to name the property.\r
+  @param[in] Value          The value (big-endian) to the property value.\r
+  @param[in] Length         The length to the size of the property.\r
+\r
+  @return  Zero for successfully, otherwise failed.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtSetProp (\r
+  IN VOID         *Fdt,\r
+  IN INT32        NodeOffset,\r
+  IN CONST CHAR8  *Name,\r
+  IN CONST VOID   *Value,\r
+  IN UINT32       Length\r
+  );\r
+\r
+#endif /* FDT_LIB_H_ */\r
diff --git a/MdePkg/Library/BaseFdtLib/BaseFdtLib.inf b/MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
new file mode 100644 (file)
index 0000000..730e568
--- /dev/null
@@ -0,0 +1,62 @@
+## @file\r
+# Flattened Device Tree Library.\r
+#\r
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x0001001B\r
+  BASE_NAME                      = BaseFdtLib\r
+  MODULE_UNI_FILE                = BaseFdtLib.uni\r
+  FILE_GUID                      = C64DCB01-B037-4FF6-9CF3-E8CEC206DE04\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = FdtLib\r
+\r
+  DEFINE FDT_LIB_PATH            = libfdt/libfdt\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  FdtLib.c\r
+  LibFdtWrapper.c\r
+  # header Wrapper files\r
+  limits.h\r
+  stdbool.h\r
+  stddef.h\r
+  stdint.h\r
+  stdlib.h\r
+  string.h\r
+\r
+  $(FDT_LIB_PATH)/fdt.c\r
+  $(FDT_LIB_PATH)/fdt.h\r
+  $(FDT_LIB_PATH)/fdt_addresses.c\r
+  $(FDT_LIB_PATH)/fdt_check.c\r
+  $(FDT_LIB_PATH)/fdt_empty_tree.c\r
+  $(FDT_LIB_PATH)/fdt_overlay.c\r
+  $(FDT_LIB_PATH)/fdt_ro.c\r
+  $(FDT_LIB_PATH)/fdt_rw.c\r
+  $(FDT_LIB_PATH)/fdt_strerror.c\r
+  $(FDT_LIB_PATH)/fdt_sw.c\r
+  $(FDT_LIB_PATH)/fdt_wip.c\r
+  $(FDT_LIB_PATH)/libfdt.h\r
+  $(FDT_LIB_PATH)/libfdt_env.h\r
+  $(FDT_LIB_PATH)/libfdt_internal.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+\r
+[BuildOptions]\r
+  MSFT:*_*_IA32_CC_FLAGS = /wd4146 /wd4245\r
+  MSFT:*_*_X64_CC_FLAGS  = /wd4146 /wd4244 /wd4245 /wd4267\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/BaseFdtLib.uni b/MdePkg/Library/BaseFdtLib/BaseFdtLib.uni
new file mode 100644 (file)
index 0000000..3f7e45e
--- /dev/null
@@ -0,0 +1,14 @@
+// /** @file\r
+// Flattened Device Tree Library.\r
+//\r
+// Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "Instance of FDT Library"\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "This module provides FDT Library implementation."\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c
new file mode 100644 (file)
index 0000000..090b0b3
--- /dev/null
@@ -0,0 +1,404 @@
+/** @file\r
+  Flattened Device Tree Library.\r
+\r
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <libfdt/libfdt/libfdt.h>\r
+\r
+/**\r
+  Convert UINT16 data of the FDT blob to little-endian\r
+\r
+  @param[in] Value            The value to the blob data.\r
+\r
+  @return The value to be converted to little-endian.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+Fdt16ToCpu (\r
+  IN UINT16  Value\r
+  )\r
+{\r
+  return fdt16_to_cpu (Value);\r
+}\r
+\r
+/**\r
+  Convert UINT16 data to big-endian for aligned with the FDT blob\r
+\r
+  @param[in] Value            The value to align with the FDT blob.\r
+\r
+  @return The value to be converted to big-endian.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+CpuToFdt16 (\r
+  IN UINT16  Value\r
+  )\r
+{\r
+  return cpu_to_fdt16 (Value);\r
+}\r
+\r
+/**\r
+  Convert UINT32 data of the FDT blob to little-endian\r
+\r
+  @param[in] Value            The value to the blob data.\r
+\r
+  @return The value to be converted to little-endian.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+Fdt32ToCpu (\r
+  IN UINT32  Value\r
+  )\r
+{\r
+  return fdt32_to_cpu (Value);\r
+}\r
+\r
+/**\r
+  Convert UINT32 data to big-endian for aligned with the FDT blob\r
+\r
+  @param[in] Value            The value to align with the FDT blob.\r
+\r
+  @return The value to be converted to big-endian.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+CpuToFdt32 (\r
+  IN UINT32  Value\r
+  )\r
+{\r
+  return cpu_to_fdt32 (Value);\r
+}\r
+\r
+/**\r
+  Convert UINT64 data of the FDT blob to little-endian\r
+\r
+  @param[in] Value            The value to the blob data.\r
+\r
+  @return The value to be converted to little-endian.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+Fdt64ToCpu (\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  return fdt64_to_cpu (Value);\r
+}\r
+\r
+/**\r
+  Convert UINT64 data to big-endian for aligned with the FDT blob\r
+\r
+  @param[in] Value            The value to align with the FDT blob.\r
+\r
+  @return The value to be converted to big-endian.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+CpuToFdt64 (\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  return cpu_to_fdt64 (Value);\r
+}\r
+\r
+/**\r
+  Verify the header of the Flattened Device Tree\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+\r
+  @return Zero for successfully, otherwise failed.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtCheckHeader (\r
+  IN CONST VOID  *Fdt\r
+  )\r
+{\r
+  return fdt_check_header (Fdt);\r
+}\r
+\r
+/**\r
+  Create a empty Flattened Device Tree.\r
+\r
+  @param[in] Buffer         The pointer to allocate a pool for FDT blob.\r
+  @param[in] BufferSize     The BufferSize to the pool size.\r
+\r
+  @return Zero for successfully, otherwise failed.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtCreateEmptyTree (\r
+  IN VOID    *Buffer,\r
+  IN UINT32  BufferSize\r
+  )\r
+{\r
+  return fdt_create_empty_tree (Buffer, (int)BufferSize);\r
+}\r
+\r
+/**\r
+  Returns a offset of next node from the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous node.\r
+  @param[in] Depth          The depth to the level of tree hierarchy.\r
+\r
+  @return The offset to next node offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNextNode (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset,\r
+  IN INT32       *Depth\r
+  )\r
+{\r
+  return fdt_next_node (Fdt, Offset, Depth);\r
+}\r
+\r
+/**\r
+  Returns a offset of first node under the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous node.\r
+\r
+  @return The offset to next node offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtFirstSubnode (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset\r
+  )\r
+{\r
+  return fdt_first_subnode (Fdt, Offset);\r
+}\r
+\r
+/**\r
+  Returns a offset of next node from the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous node.\r
+\r
+  @return The offset to next node offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNextSubnode (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset\r
+  )\r
+{\r
+  return fdt_next_subnode (Fdt, Offset);\r
+}\r
+\r
+/**\r
+  Returns a offset of first node which includes the given name.\r
+\r
+  @param[in] Fdt             The pointer to FDT blob.\r
+  @param[in] ParentOffset    The offset to the node which start find under.\r
+  @param[in] Name            The name to search the node with the name.\r
+  @param[in] NameLength      The length of the name to check only.\r
+\r
+  @return The offset to node offset with given node name.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtSubnodeOffsetNameLen (\r
+  IN CONST VOID   *Fdt,\r
+  IN INT32        ParentOffset,\r
+  IN CONST CHAR8  *Name,\r
+  IN INT32        NameLength\r
+  )\r
+{\r
+  return fdt_subnode_offset_namelen (Fdt, ParentOffset, Name, NameLength);\r
+}\r
+\r
+/**\r
+  Returns a offset of first node which includes the given property name and value.\r
+\r
+  @param[in] Fdt             The pointer to FDT blob.\r
+  @param[in] StartOffset     The offset to the starting node to find.\r
+  @param[in] PropertyName    The property name to search the node including the named property.\r
+  @param[in] PropertyValue   The property value (big-endian) to check the same property value.\r
+  @param[in] PropertyLength  The length of the value in PropertValue.\r
+\r
+  @return The offset to node offset with given property.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNodeOffsetByPropValue (\r
+  IN CONST VOID   *Fdt,\r
+  IN INT32        StartOffset,\r
+  IN CONST CHAR8  *PropertyName,\r
+  IN CONST VOID   *PropertyValue,\r
+  IN INT32        PropertyLength\r
+  )\r
+{\r
+  return fdt_node_offset_by_prop_value (Fdt, StartOffset, PropertyName, PropertyValue, PropertyLength);\r
+}\r
+\r
+/**\r
+  Returns a property with the given name from the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] NodeOffset     The offset to the given node.\r
+  @param[in] Name           The name to the property which need be searched\r
+  @param[in] Length         The length to the size of the property found.\r
+\r
+  @return The property to the structure of the found property. Since the data\r
+          come from FDT blob, it's encoding with big-endian.\r
+\r
+**/\r
+CONST struct fdt_property *\r
+EFIAPI\r
+FdtGetProperty (\r
+  IN CONST VOID   *Fdt,\r
+  IN INT32        NodeOffset,\r
+  IN CONST CHAR8  *Name,\r
+  IN INT32        *Length\r
+  )\r
+{\r
+  return fdt_get_property (Fdt, NodeOffset, Name, Length);\r
+}\r
+\r
+/**\r
+  Returns a offset of first property in the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] NodeOffset     The offset to the node which need be searched.\r
+\r
+  @return The offset to first property offset in the given node.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtFirstPropertyOffset (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       NodeOffset\r
+  )\r
+{\r
+  return fdt_first_property_offset (Fdt, NodeOffset);\r
+}\r
+\r
+/**\r
+  Returns a offset of next property from the given property.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to previous property.\r
+\r
+  @return The offset to next property offset.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtNextPropertyOffset (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset\r
+  )\r
+{\r
+  return fdt_next_property_offset (Fdt, Offset);\r
+}\r
+\r
+/**\r
+  Returns a property from the given offset of the property.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] Offset         The offset to the given offset of the property.\r
+  @param[in] Length         The length to the size of the property found.\r
+\r
+  @return The property to the structure of the given property offset.\r
+\r
+**/\r
+CONST struct fdt_property *\r
+EFIAPI\r
+FdtGetPropertyByOffset (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       Offset,\r
+  IN INT32       *Length\r
+  )\r
+{\r
+  return fdt_get_property_by_offset (Fdt, Offset, Length);\r
+}\r
+\r
+/**\r
+  Returns a string by the given string offset.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] StrOffset      The offset to the location in the strings block of FDT.\r
+  @param[in] Length         The length to the size of string which need be retrieved.\r
+\r
+  @return The string to the given string offset.\r
+\r
+**/\r
+CONST CHAR8 *\r
+EFIAPI\r
+FdtGetString (\r
+  IN CONST VOID  *Fdt,\r
+  IN INT32       StrOffset,\r
+  IN INT32       *Length        OPTIONAL\r
+  )\r
+{\r
+  return fdt_get_string (Fdt, StrOffset, Length);\r
+}\r
+\r
+/**\r
+  Add a new node to the FDT.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] ParentOffset   The offset to the node offset which want to add in.\r
+  @param[in] Name           The name to name the node.\r
+\r
+  @return  The offset to the new node.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtAddSubnode (\r
+  IN VOID         *Fdt,\r
+  IN INT32        ParentOffset,\r
+  IN CONST CHAR8  *Name\r
+  )\r
+{\r
+  return fdt_add_subnode (Fdt, ParentOffset, Name);\r
+}\r
+\r
+/**\r
+  Add or modify a property in the given node.\r
+\r
+  @param[in] Fdt            The pointer to FDT blob.\r
+  @param[in] NodeOffset     The offset to the node offset which want to add in.\r
+  @param[in] Name           The name to name the property.\r
+  @param[in] Value          The value (big-endian) to the property value.\r
+  @param[in] Length         The length to the size of the property.\r
+\r
+  @return  Zero for successfully, otherwise failed.\r
+\r
+**/\r
+INT32\r
+EFIAPI\r
+FdtSetProp (\r
+  IN VOID         *Fdt,\r
+  IN INT32        NodeOffset,\r
+  IN CONST CHAR8  *Name,\r
+  IN CONST VOID   *Value,\r
+  IN UINT32       Length\r
+  )\r
+{\r
+  return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length);\r
+}\r
diff --git a/MdePkg/Library/BaseFdtLib/LibFdtSupport.h b/MdePkg/Library/BaseFdtLib/LibFdtSupport.h
new file mode 100644 (file)
index 0000000..3930193
--- /dev/null
@@ -0,0 +1,99 @@
+/** @file\r
+  Root include file of C runtime library to support building the third-party\r
+  libfdt library.\r
+\r
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef FDT_LIB_SUPPORT_H_\r
+#define FDT_LIB_SUPPORT_H_\r
+\r
+#include <Base.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+typedef UINT8    uint8_t;\r
+typedef UINT16   uint16_t;\r
+typedef INT32    int32_t;\r
+typedef UINT32   uint32_t;\r
+typedef UINT64   uint64_t;\r
+typedef UINTN    uintptr_t;\r
+typedef UINTN    size_t;\r
+typedef BOOLEAN  bool;\r
+\r
+#define true   (1 == 1)\r
+#define false  (1 == 0)\r
+\r
+//\r
+// Definitions for global constants used by libfdt library routines\r
+//\r
+#define INT_MAX     0x7FFFFFFF           /* Maximum (signed) int value */\r
+#define INT32_MAX   0x7FFFFFFF           /* Maximum (signed) int32 value */\r
+#define UINT32_MAX  0xFFFFFFFF           /* Maximum unsigned int32 value */\r
+\r
+//\r
+// Function prototypes of libfdt Library routines\r
+//\r
+void *\r
+memset     (\r
+  void *,\r
+  int,\r
+  size_t\r
+  );\r
+\r
+int\r
+memcmp      (\r
+  const void *,\r
+  const void *,\r
+  size_t\r
+  );\r
+\r
+int\r
+strcmp      (\r
+  const char *,\r
+  const char *\r
+  );\r
+\r
+char *\r
+strchr     (\r
+  const char *,\r
+  int\r
+  );\r
+\r
+char *\r
+strrchr    (\r
+  const char *,\r
+  int\r
+  );\r
+\r
+unsigned long\r
+strtoul     (\r
+  const char *,\r
+  char **,\r
+  int\r
+  );\r
+\r
+char *\r
+strcpy (\r
+  char        *strDest,\r
+  const char  *strSource\r
+  );\r
+\r
+//\r
+// Macros that directly map functions to BaseLib, BaseMemoryLib, and DebugLib functions\r
+//\r
+#define memcpy(dest, source, count)         CopyMem(dest,source, (UINTN)(count))\r
+#define memset(dest, ch, count)             SetMem(dest, (UINTN)(count),(UINT8)(ch))\r
+#define memchr(buf, ch, count)              ScanMem8(buf, (UINTN)(count),(UINT8)ch)\r
+#define memcmp(buf1, buf2, count)           (int)(CompareMem(buf1, buf2, (UINTN)(count)))\r
+#define memmove(dest, source, count)        CopyMem(dest, source, (UINTN)(count))\r
+#define strlen(str)                         (size_t)(AsciiStrLen(str))\r
+#define strnlen(str, count)                 (size_t)(AsciiStrnLenS(str, count))\r
+#define strncpy(strDest, strSource, count)  AsciiStrnCpyS(strDest, MAX_STRING_SIZE, strSource, (UINTN)count)\r
+#define strcat(strDest, strSource)          AsciiStrCatS(strDest, MAX_STRING_SIZE, strSource)\r
+#define strcmp(string1, string2, count)     (int)(AsciiStrCmp(string1, string2))\r
+#define strncmp(string1, string2, count)    (int)(AsciiStrnCmp(string1, string2, (UINTN)(count)))\r
+\r
+#endif /* FDT_LIB_SUPPORT_H_ */\r
diff --git a/MdePkg/Library/BaseFdtLib/LibFdtWrapper.c b/MdePkg/Library/BaseFdtLib/LibFdtWrapper.c
new file mode 100644 (file)
index 0000000..ef64529
--- /dev/null
@@ -0,0 +1,173 @@
+/** @file\r
+  ISO C implementations of strchr, strrchr and strtoul.\r
+\r
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2023 Pedro Falcato All rights reserved.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+\r
+#define ULONG_MAX  0xFFFFFFFF            /* Maximum unsigned long value */\r
+\r
+// Very quick notes:\r
+// We only go through the string once for both functions\r
+// They are minimal implementations (not speed optimized) of ISO C semantics\r
+// strchr and strrchr also include the null terminator as part of the string\r
+// so the code gets a bit clunky to handle that case specifically.\r
+\r
+char *\r
+strchr (\r
+  const char  *Str,\r
+  int         Char\r
+  )\r
+{\r
+  char  *S;\r
+\r
+  S = (char *)Str;\r
+\r
+  for ( ; ; S++) {\r
+    if (*S == Char) {\r
+      return S;\r
+    }\r
+\r
+    if (*S == '\0') {\r
+      return NULL;\r
+    }\r
+  }\r
+}\r
+\r
+char *\r
+strrchr (\r
+  const char  *Str,\r
+  int         Char\r
+  )\r
+{\r
+  char  *S, *last;\r
+\r
+  S    = (char *)Str;\r
+  last = NULL;\r
+\r
+  for ( ; ; S++) {\r
+    if (*S == Char) {\r
+      last = S;\r
+    }\r
+\r
+    if (*S == '\0') {\r
+      return last;\r
+    }\r
+  }\r
+}\r
+\r
+STATIC\r
+int\r
+__isspace (\r
+  int  ch\r
+  )\r
+{\r
+  // basic ASCII ctype.h:isspace(). Not efficient\r
+  return ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f';\r
+}\r
+\r
+unsigned long\r
+strtoul (\r
+  const char  *Nptr,\r
+  char        **EndPtr,\r
+  int         Base\r
+  )\r
+{\r
+  BOOLEAN        Negate;\r
+  BOOLEAN        Overflow;\r
+  unsigned long  Val;\r
+\r
+  Negate   = FALSE;\r
+  Overflow = FALSE;\r
+  Val      = 0;\r
+\r
+  // Reject bad numeric bases\r
+  if ((Base < 0) || (Base == 1) || (Base > 36)) {\r
+    return 0;\r
+  }\r
+\r
+  // Skip whitespace\r
+  while (__isspace (*Nptr)) {\r
+    Nptr++;\r
+  }\r
+\r
+  // Check for + or - prefixes\r
+  if (*Nptr == '-') {\r
+    Negate = TRUE;\r
+    Nptr++;\r
+  } else if (*Nptr == '+') {\r
+    Nptr++;\r
+  }\r
+\r
+  // Consume the start, autodetecting base if needed\r
+  if ((Nptr[0] == '0') && ((Nptr[1] == 'x') || (Nptr[1] == 'X')) && ((Base == 0) || (Base == 16))) {\r
+    // Hex\r
+    Nptr += 2;\r
+    Base  = 16;\r
+  } else if ((Nptr[0] == '0') && ((Nptr[1] == 'b') || (Nptr[1] == 'B')) && ((Base == 0) || (Base == 2))) {\r
+    // Binary (standard pending C23)\r
+    Nptr += 2;\r
+    Base  = 2;\r
+  } else if ((Nptr[0] == '0') && ((Base == 0) || (Base == 8))) {\r
+    // Octal\r
+    Nptr++;\r
+    Base = 8;\r
+  } else {\r
+    if (Base == 0) {\r
+      // Assume decimal\r
+      Base = 10;\r
+    }\r
+  }\r
+\r
+  while (TRUE) {\r
+    int            Digit;\r
+    char           C;\r
+    unsigned long  NewVal;\r
+\r
+    C     = *Nptr;\r
+    Digit = -1;\r
+\r
+    if ((C >= '0') && (C <= '9')) {\r
+      Digit = C - '0';\r
+    } else if ((C >= 'a') && (C <= 'z')) {\r
+      Digit = C - 'a' + 10;\r
+    } else if ((C >= 'A') && (C <= 'Z')) {\r
+      Digit = C - 'A' + 10;\r
+    }\r
+\r
+    if ((Digit == -1) || (Digit >= Base)) {\r
+      // Note that this case also handles the \0\r
+      if (EndPtr) {\r
+        *EndPtr = (char *)Nptr;\r
+      }\r
+\r
+      break;\r
+    }\r
+\r
+    NewVal = Val * Base + Digit;\r
+\r
+    if (NewVal < Val) {\r
+      // Overflow\r
+      Overflow = TRUE;\r
+    }\r
+\r
+    Val = NewVal;\r
+\r
+    Nptr++;\r
+  }\r
+\r
+  if (Negate) {\r
+    Val = -Val;\r
+  }\r
+\r
+  if (Overflow) {\r
+    Val = ULONG_MAX;\r
+  }\r
+\r
+  // TODO: We're lacking errno here.\r
+  return Val;\r
+}\r
diff --git a/MdePkg/Library/BaseFdtLib/limits.h b/MdePkg/Library/BaseFdtLib/limits.h
new file mode 100644 (file)
index 0000000..f6cf8d5
--- /dev/null
@@ -0,0 +1,10 @@
+/** @file\r
+  Include file to support building the third-party libfdt library.\r
+\r
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <LibFdtSupport.h>\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/stdbool.h b/MdePkg/Library/BaseFdtLib/stdbool.h
new file mode 100644 (file)
index 0000000..f6cf8d5
--- /dev/null
@@ -0,0 +1,10 @@
+/** @file\r
+  Include file to support building the third-party libfdt library.\r
+\r
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <LibFdtSupport.h>\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/stddef.h b/MdePkg/Library/BaseFdtLib/stddef.h
new file mode 100644 (file)
index 0000000..f6cf8d5
--- /dev/null
@@ -0,0 +1,10 @@
+/** @file\r
+  Include file to support building the third-party libfdt library.\r
+\r
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <LibFdtSupport.h>\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/stdint.h b/MdePkg/Library/BaseFdtLib/stdint.h
new file mode 100644 (file)
index 0000000..f6cf8d5
--- /dev/null
@@ -0,0 +1,10 @@
+/** @file\r
+  Include file to support building the third-party libfdt library.\r
+\r
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <LibFdtSupport.h>\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/stdlib.h b/MdePkg/Library/BaseFdtLib/stdlib.h
new file mode 100644 (file)
index 0000000..f6cf8d5
--- /dev/null
@@ -0,0 +1,10 @@
+/** @file\r
+  Include file to support building the third-party libfdt library.\r
+\r
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <LibFdtSupport.h>\r
+\r
diff --git a/MdePkg/Library/BaseFdtLib/string.h b/MdePkg/Library/BaseFdtLib/string.h
new file mode 100644 (file)
index 0000000..f6cf8d5
--- /dev/null
@@ -0,0 +1,10 @@
+/** @file\r
+  Include file to support building the third-party libfdt library.\r
+\r
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <LibFdtSupport.h>\r
+\r
index 6ba85ebe6186f87f5873c304557cc18f1b3ce24b..035c34b3adfe552be04befebc23fd1182f485967 100644 (file)
@@ -67,7 +67,8 @@
             "Include/Library/PcdLib.h",\r
             "Include/Library/SafeIntLib.h",\r
             "Include/Protocol/DebugSupport.h",\r
-            "Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.c"\r
+            "Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.c",\r
+            "Library/BaseFdtLib"\r
         ]\r
     },\r
     ## options defined ci/Plugin/CompilerPlugin\r
         "ExtendWords": [],           # words to extend to the dictionary for this package\r
         "IgnoreStandardPaths": [],   # Standard Plugin defined paths that should be ignore\r
         "AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)\r
+    },\r
+    # options defined in .pytool/Plugin/UncrustifyCheck\r
+    "UncrustifyCheck": {\r
+        "IgnoreFiles": [\r
+            "Library/BaseFdtLib/libfdt",\r
+            "Library/BaseFdtLib/limits.h",\r
+            "Library/BaseFdtLib/stdbool.h",\r
+            "Library/BaseFdtLib/stddef.h",\r
+            "Library/BaseFdtLib/stdint.h",\r
+            "Library/BaseFdtLib/stdlib.h",\r
+            "Library/BaseFdtLib/string.h"\r
+        ]\r
     }\r
 }\r
index 7488ccda7a00644c3024ca504601d2432e2d03b8..d6c4179b2a48852b32e2cc567799c76bb2f2ccff 100644 (file)
   #\r
   ArmTrngLib|Include/Library/ArmTrngLib.h\r
 \r
+  ##  @libraryclass  Provides APIs for third-party library libfdt.\r
+  #\r
+  FdtLib|Include/Library/FdtLib.h\r
+\r
 [LibraryClasses.IA32, LibraryClasses.X64, LibraryClasses.AARCH64]\r
   ##  @libraryclass  Provides services to generate random number.\r
   #\r
index 152c02991a7c54dc107e941071df68c4fb0cf7db..b38c863812c174d48430cda0cacc1b756f7e3dd1 100644 (file)
   MdePkg/Library/SmmCpuRendezvousLibNull/SmmCpuRendezvousLibNull.inf\r
 \r
   MdePkg/Library/JedecJep106Lib/JedecJep106Lib.inf\r
+  MdePkg/Library/BaseFdtLib/BaseFdtLib.inf\r
 \r
 [Components.IA32, Components.X64, Components.ARM, Components.AARCH64]\r
   #\r