REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the EmbeddedPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
		
			
				
	
	
		
			499 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			499 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| *  FDT client driver
 | |
| *
 | |
| *  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
 | |
| *
 | |
| *  SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| *
 | |
| **/
 | |
| 
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/UefiDriverEntryPoint.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/HobLib.h>
 | |
| #include <libfdt.h>
 | |
| 
 | |
| #include <Guid/Fdt.h>
 | |
| #include <Guid/FdtHob.h>
 | |
| #include <Guid/PlatformHasDeviceTree.h>
 | |
| 
 | |
| #include <Protocol/FdtClient.h>
 | |
| 
 | |
| STATIC VOID  *mDeviceTreeBase;
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetNodeProperty (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  INT32                Node,
 | |
|   IN  CONST CHAR8          *PropertyName,
 | |
|   OUT CONST VOID           **Prop,
 | |
|   OUT UINT32               *PropSize OPTIONAL
 | |
|   )
 | |
| {
 | |
|   INT32  Len;
 | |
| 
 | |
|   ASSERT (mDeviceTreeBase != NULL);
 | |
|   ASSERT (Prop != NULL);
 | |
| 
 | |
|   *Prop = fdt_getprop (mDeviceTreeBase, Node, PropertyName, &Len);
 | |
|   if (*Prop == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   if (PropSize != NULL) {
 | |
|     *PropSize = Len;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SetNodeProperty (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  INT32                Node,
 | |
|   IN  CONST CHAR8          *PropertyName,
 | |
|   IN  CONST VOID           *Prop,
 | |
|   IN  UINT32               PropSize
 | |
|   )
 | |
| {
 | |
|   INT32  Ret;
 | |
| 
 | |
|   ASSERT (mDeviceTreeBase != NULL);
 | |
| 
 | |
|   Ret = fdt_setprop (mDeviceTreeBase, Node, PropertyName, Prop, PropSize);
 | |
|   if (Ret != 0) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| BOOLEAN
 | |
| IsNodeEnabled (
 | |
|   INT32  Node
 | |
|   )
 | |
| {
 | |
|   CONST CHAR8  *NodeStatus;
 | |
|   INT32        Len;
 | |
| 
 | |
|   //
 | |
|   // A missing status property implies 'ok' so ignore any errors that
 | |
|   // may occur here. If the status property is present, check whether
 | |
|   // it is set to 'ok' or 'okay', anything else is treated as 'disabled'.
 | |
|   //
 | |
|   NodeStatus = fdt_getprop (mDeviceTreeBase, Node, "status", &Len);
 | |
|   if (NodeStatus == NULL) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((Len >= 5) && (AsciiStrCmp (NodeStatus, "okay") == 0)) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((Len >= 3) && (AsciiStrCmp (NodeStatus, "ok") == 0)) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FindNextCompatibleNode (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  CONST CHAR8          *CompatibleString,
 | |
|   IN  INT32                PrevNode,
 | |
|   OUT INT32                *Node
 | |
|   )
 | |
| {
 | |
|   INT32        Prev, Next;
 | |
|   CONST CHAR8  *Type, *Compatible;
 | |
|   INT32        Len;
 | |
| 
 | |
|   ASSERT (mDeviceTreeBase != NULL);
 | |
|   ASSERT (Node != NULL);
 | |
| 
 | |
|   for (Prev = PrevNode; ; Prev = Next) {
 | |
|     Next = fdt_next_node (mDeviceTreeBase, Prev, NULL);
 | |
|     if (Next < 0) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (!IsNodeEnabled (Next)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Type = fdt_getprop (mDeviceTreeBase, Next, "compatible", &Len);
 | |
|     if (Type == NULL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // A 'compatible' node may contain a sequence of NUL terminated
 | |
|     // compatible strings so check each one
 | |
|     //
 | |
|     for (Compatible = Type; Compatible < Type + Len && *Compatible;
 | |
|          Compatible += 1 + AsciiStrLen (Compatible))
 | |
|     {
 | |
|       if (AsciiStrCmp (CompatibleString, Compatible) == 0) {
 | |
|         *Node = Next;
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FindCompatibleNode (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  CONST CHAR8          *CompatibleString,
 | |
|   OUT INT32                *Node
 | |
|   )
 | |
| {
 | |
|   return FindNextCompatibleNode (This, CompatibleString, 0, Node);
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FindCompatibleNodeProperty (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  CONST CHAR8          *CompatibleString,
 | |
|   IN  CONST CHAR8          *PropertyName,
 | |
|   OUT CONST VOID           **Prop,
 | |
|   OUT UINT32               *PropSize OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INT32       Node;
 | |
| 
 | |
|   Status = FindCompatibleNode (This, CompatibleString, &Node);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return GetNodeProperty (This, Node, PropertyName, Prop, PropSize);
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FindCompatibleNodeReg (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  CONST CHAR8          *CompatibleString,
 | |
|   OUT CONST VOID           **Reg,
 | |
|   OUT UINTN                *AddressCells,
 | |
|   OUT UINTN                *SizeCells,
 | |
|   OUT UINT32               *RegSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   ASSERT (RegSize != NULL);
 | |
| 
 | |
|   //
 | |
|   // Get the 'reg' property of this node. For now, we will assume
 | |
|   // 8 byte quantities for base and size, respectively.
 | |
|   // TODO use #cells root properties instead
 | |
|   //
 | |
|   Status = FindCompatibleNodeProperty (
 | |
|              This,
 | |
|              CompatibleString,
 | |
|              "reg",
 | |
|              Reg,
 | |
|              RegSize
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if ((*RegSize % 16) != 0) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a: '%a' compatible node has invalid 'reg' property (size == 0x%x)\n",
 | |
|       __FUNCTION__,
 | |
|       CompatibleString,
 | |
|       *RegSize
 | |
|       ));
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   *AddressCells = 2;
 | |
|   *SizeCells    = 2;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FindNextMemoryNodeReg (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   IN  INT32                PrevNode,
 | |
|   OUT INT32                *Node,
 | |
|   OUT CONST VOID           **Reg,
 | |
|   OUT UINTN                *AddressCells,
 | |
|   OUT UINTN                *SizeCells,
 | |
|   OUT UINT32               *RegSize
 | |
|   )
 | |
| {
 | |
|   INT32        Prev, Next;
 | |
|   CONST CHAR8  *DeviceType;
 | |
|   INT32        Len;
 | |
|   EFI_STATUS   Status;
 | |
| 
 | |
|   ASSERT (mDeviceTreeBase != NULL);
 | |
|   ASSERT (Node != NULL);
 | |
| 
 | |
|   for (Prev = PrevNode; ; Prev = Next) {
 | |
|     Next = fdt_next_node (mDeviceTreeBase, Prev, NULL);
 | |
|     if (Next < 0) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (!IsNodeEnabled (Next)) {
 | |
|       DEBUG ((DEBUG_WARN, "%a: ignoring disabled memory node\n", __FUNCTION__));
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DeviceType = fdt_getprop (mDeviceTreeBase, Next, "device_type", &Len);
 | |
|     if ((DeviceType != NULL) && (AsciiStrCmp (DeviceType, "memory") == 0)) {
 | |
|       //
 | |
|       // Get the 'reg' property of this memory node. For now, we will assume
 | |
|       // 8 byte quantities for base and size, respectively.
 | |
|       // TODO use #cells root properties instead
 | |
|       //
 | |
|       Status = GetNodeProperty (This, Next, "reg", Reg, RegSize);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         DEBUG ((
 | |
|           DEBUG_WARN,
 | |
|           "%a: ignoring memory node with no 'reg' property\n",
 | |
|           __FUNCTION__
 | |
|           ));
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if ((*RegSize % 16) != 0) {
 | |
|         DEBUG ((
 | |
|           DEBUG_WARN,
 | |
|           "%a: ignoring memory node with invalid 'reg' property (size == 0x%x)\n",
 | |
|           __FUNCTION__,
 | |
|           *RegSize
 | |
|           ));
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       *Node         = Next;
 | |
|       *AddressCells = 2;
 | |
|       *SizeCells    = 2;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FindMemoryNodeReg (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   OUT INT32                *Node,
 | |
|   OUT CONST VOID           **Reg,
 | |
|   OUT UINTN                *AddressCells,
 | |
|   OUT UINTN                *SizeCells,
 | |
|   OUT UINT32               *RegSize
 | |
|   )
 | |
| {
 | |
|   return FindNextMemoryNodeReg (
 | |
|            This,
 | |
|            0,
 | |
|            Node,
 | |
|            Reg,
 | |
|            AddressCells,
 | |
|            SizeCells,
 | |
|            RegSize
 | |
|            );
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetOrInsertChosenNode (
 | |
|   IN  FDT_CLIENT_PROTOCOL  *This,
 | |
|   OUT INT32                *Node
 | |
|   )
 | |
| {
 | |
|   INT32  NewNode;
 | |
| 
 | |
|   ASSERT (mDeviceTreeBase != NULL);
 | |
|   ASSERT (Node != NULL);
 | |
| 
 | |
|   NewNode = fdt_path_offset (mDeviceTreeBase, "/chosen");
 | |
|   if (NewNode < 0) {
 | |
|     NewNode = fdt_add_subnode (mDeviceTreeBase, 0, "/chosen");
 | |
|   }
 | |
| 
 | |
|   if (NewNode < 0) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   *Node = NewNode;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC FDT_CLIENT_PROTOCOL  mFdtClientProtocol = {
 | |
|   GetNodeProperty,
 | |
|   SetNodeProperty,
 | |
|   FindCompatibleNode,
 | |
|   FindNextCompatibleNode,
 | |
|   FindCompatibleNodeProperty,
 | |
|   FindCompatibleNodeReg,
 | |
|   FindMemoryNodeReg,
 | |
|   FindNextMemoryNodeReg,
 | |
|   GetOrInsertChosenNode,
 | |
| };
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| OnPlatformHasDeviceTree (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   VOID        *Interface;
 | |
|   VOID        *DeviceTreeBase;
 | |
| 
 | |
|   Status = gBS->LocateProtocol (
 | |
|                   &gEdkiiPlatformHasDeviceTreeGuid,
 | |
|                   NULL,                             // Registration
 | |
|                   &Interface
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   DeviceTreeBase = Context;
 | |
|   DEBUG ((
 | |
|     DEBUG_INFO,
 | |
|     "%a: exposing DTB @ 0x%p to OS\n",
 | |
|     __FUNCTION__,
 | |
|     DeviceTreeBase
 | |
|     ));
 | |
|   Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   gBS->CloseEvent (Event);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InitializeFdtClientDxe (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   VOID        *Hob;
 | |
|   VOID        *DeviceTreeBase;
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_EVENT   PlatformHasDeviceTreeEvent;
 | |
|   VOID        *Registration;
 | |
| 
 | |
|   Hob = GetFirstGuidHob (&gFdtHobGuid);
 | |
|   if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64))) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);
 | |
| 
 | |
|   if (fdt_check_header (DeviceTreeBase) != 0) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a: No DTB found @ 0x%p\n",
 | |
|       __FUNCTION__,
 | |
|       DeviceTreeBase
 | |
|       ));
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   mDeviceTreeBase = DeviceTreeBase;
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, mDeviceTreeBase));
 | |
| 
 | |
|   //
 | |
|   // Register a protocol notify for the EDKII Platform Has Device Tree
 | |
|   // Protocol.
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   OnPlatformHasDeviceTree,
 | |
|                   DeviceTreeBase,             // Context
 | |
|                   &PlatformHasDeviceTreeEvent
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "%a: CreateEvent(): %r\n", __FUNCTION__, Status));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->RegisterProtocolNotify (
 | |
|                   &gEdkiiPlatformHasDeviceTreeGuid,
 | |
|                   PlatformHasDeviceTreeEvent,
 | |
|                   &Registration
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a: RegisterProtocolNotify(): %r\n",
 | |
|       __FUNCTION__,
 | |
|       Status
 | |
|       ));
 | |
|     goto CloseEvent;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Kick the event; the protocol could be available already.
 | |
|   //
 | |
|   Status = gBS->SignalEvent (PlatformHasDeviceTreeEvent);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "%a: SignalEvent(): %r\n", __FUNCTION__, Status));
 | |
|     goto CloseEvent;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &ImageHandle,
 | |
|                   &gFdtClientProtocolGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   &mFdtClientProtocol
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a: InstallProtocolInterface(): %r\n",
 | |
|       __FUNCTION__,
 | |
|       Status
 | |
|       ));
 | |
|     goto CloseEvent;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| 
 | |
| CloseEvent:
 | |
|   gBS->CloseEvent (PlatformHasDeviceTreeEvent);
 | |
|   return Status;
 | |
| }
 |