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;
 | 
						|
}
 |