/** @file
  Determine the base addresses of serial ports from the Device Tree.

  Copyright (C) Red Hat
  Copyright (c) 2011 - 2023, Arm Ltd. All rights reserved.<BR>
  Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
  Copyright (c) 2014 - 2020, Linaro Ltd. All rights reserved.<BR>
  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Library/BaseLib.h>
#include <Library/FdtLib.h>
#include <Library/FdtSerialPortAddressLib.h>

/**
  Read the "reg" property of Node in DeviceTree as a UINT64 base address.

  @param[in] DeviceTree    The flat device tree (FDT) to scan.

  @param[in] Node          The node to read the "reg" property of.

  @param[out] BaseAddress  On success, the base address read out of Node's "reg"
                           property. On error, not modified.

  @retval RETURN_DEVICE_ERROR     Node has a "status" property with value
                                  different from "okay".

  @retval RETURN_NOT_FOUND        Node does not have a "reg" property.

  @retval RETURN_BAD_BUFFER_SIZE  The size of Node's "reg" property is not 16
                                  bytes.

  @retval RETURN_SUCCESS          BaseAddress has been populated.
**/
STATIC
RETURN_STATUS
GetBaseAddress (
  IN  CONST VOID  *DeviceTree,
  IN  INT32       Node,
  OUT UINT64      *BaseAddress
  )
{
  CONST CHAR8  *NodeStatus;
  CONST VOID   *RegProp;
  INT32        PropSize;

  NodeStatus = FdtGetProp (DeviceTree, Node, "status", NULL);
  if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
    return RETURN_DEVICE_ERROR;
  }

  RegProp = FdtGetProp (DeviceTree, Node, "reg", &PropSize);
  if (RegProp == NULL) {
    return RETURN_NOT_FOUND;
  }

  if (PropSize != 16) {
    return RETURN_BAD_BUFFER_SIZE;
  }

  *BaseAddress = Fdt64ToCpu (ReadUnaligned64 (RegProp));
  return RETURN_SUCCESS;
}

/**
  Collect the first ARRAY_SIZE (Ports->BaseAddress) serial ports into Ports from
  DeviceTree.

  @param[in] DeviceTree  The flat device tree (FDT) to scan.

  @param[in] Compatible  Look for Compatible in the "compatible" property of the
                         scanned nodes.

  @param[out] Ports      On successful return, Ports->NumberOfPorts contains the
                         number of serial ports found; it is (a) positive and
                         (b) at most ARRAY_SIZE (Ports->BaseAddress). If the FDT
                         had more serial ports, those are not reported. On
                         error, the contents of Ports are indeterminate.

  @retval RETURN_INVALID_PARAMETER  DeviceTree does not point to a valid FDT
                                    header.

  @retval RETURN_NOT_FOUND          No compatible and enabled serial port has
                                    been found.

  @retval RETURN_SUCCESS            At least one compatible and enabled serial
                                    port has been found; Ports has been filled
                                    in.
**/
RETURN_STATUS
EFIAPI
FdtSerialGetPorts (
  IN  CONST VOID        *DeviceTree,
  IN  CONST CHAR8       *Compatible,
  OUT FDT_SERIAL_PORTS  *Ports
  )
{
  INT32  Node;

  if (FdtCheckHeader (DeviceTree) != 0) {
    return RETURN_INVALID_PARAMETER;
  }

  Ports->NumberOfPorts = 0;
  Node                 = FdtNextNode (DeviceTree, 0, NULL);
  while ((Node > 0) &&
         (Ports->NumberOfPorts < ARRAY_SIZE (Ports->BaseAddress)))
  {
    CONST CHAR8  *CompatProp;
    INT32        PropSize;

    CompatProp = FdtGetProp (DeviceTree, Node, "compatible", &PropSize);
    if (CompatProp != NULL) {
      CONST CHAR8  *CompatItem;

      CompatItem = CompatProp;
      while ((CompatItem < CompatProp + PropSize) &&
             (AsciiStrCmp (CompatItem, Compatible) != 0))
      {
        CompatItem += AsciiStrLen (CompatItem) + 1;
      }

      if (CompatItem < CompatProp + PropSize) {
        RETURN_STATUS  Status;
        UINT64         BaseAddress;

        Status = GetBaseAddress (DeviceTree, Node, &BaseAddress);
        if (!RETURN_ERROR (Status)) {
          Ports->BaseAddress[Ports->NumberOfPorts++] = BaseAddress;
        }
      }
    }

    Node = FdtNextNode (DeviceTree, Node, NULL);
  }

  return Ports->NumberOfPorts > 0 ? RETURN_SUCCESS : RETURN_NOT_FOUND;
}

/**
  Fetch the base address of the serial port identified in the "stdout-path"
  property of the "/chosen" node in DeviceTree.

  @param[in] DeviceTree    The flat device tree (FDT) to scan.

  @param[out] BaseAddress  On success, the base address of the preferred serial
                           port (to be used as console). On error, BaseAddress
                           is not modified.

  @retval RETURN_INVALID_PARAMETER  DeviceTree does not point to a valid FDT
                                    header.

  @retval RETURN_NOT_FOUND          No enabled console port has been found.

  @retval RETURN_PROTOCOL_ERROR     The first (or only) node path in the
                                    "stdout-path" property is an empty string.

  @retval RETURN_PROTOCOL_ERROR     The console port has been found in the FDT,
                                    but its base address is not correctly
                                    represented.

  @retval RETURN_SUCCESS            BaseAddress has been populated.
**/
RETURN_STATUS
EFIAPI
FdtSerialGetConsolePort (
  IN  CONST VOID  *DeviceTree,
  OUT UINT64      *BaseAddress
  )
{
  INT32          ChosenNode;
  CONST CHAR8    *StdoutPathProp;
  INT32          PropSize;
  CONST CHAR8    *StdoutPathEnd;
  UINTN          StdoutPathLength;
  INT32          ConsoleNode;
  RETURN_STATUS  Status;

  if (FdtCheckHeader (DeviceTree) != 0) {
    return RETURN_INVALID_PARAMETER;
  }

  ChosenNode = FdtPathOffset (DeviceTree, "/chosen");
  if (ChosenNode < 0) {
    return RETURN_NOT_FOUND;
  }

  StdoutPathProp = FdtGetProp (
                     DeviceTree,
                     ChosenNode,
                     "stdout-path",
                     &PropSize
                     );
  if (StdoutPathProp == NULL) {
    return RETURN_NOT_FOUND;
  }

  //
  // If StdoutPathProp contains a colon (":"), then the colon terminates the
  // path we're interested in.
  //
  StdoutPathEnd = AsciiStrStr (StdoutPathProp, ":");
  if (StdoutPathEnd == NULL) {
    StdoutPathLength = PropSize - 1;
  } else {
    StdoutPathLength = StdoutPathEnd - StdoutPathProp;
  }

  if (StdoutPathLength == 0) {
    return RETURN_PROTOCOL_ERROR;
  }

  if (StdoutPathProp[0] == '/') {
    //
    // StdoutPathProp starts with an absolute node path.
    //
    ConsoleNode = FdtPathOffsetNameLen (
                    DeviceTree,
                    StdoutPathProp,
                    (INT32)StdoutPathLength
                    );
  } else {
    //
    // StdoutPathProp starts with an alias.
    //
    CONST CHAR8  *ResolvedStdoutPath;

    ResolvedStdoutPath = FdtGetAliasNameLen (
                           DeviceTree,
                           StdoutPathProp,
                           (INT32)StdoutPathLength
                           );
    if (ResolvedStdoutPath == NULL) {
      return RETURN_NOT_FOUND;
    }

    ConsoleNode = FdtPathOffset (DeviceTree, ResolvedStdoutPath);
  }

  if (ConsoleNode < 0) {
    return RETURN_NOT_FOUND;
  }

  Status = GetBaseAddress (DeviceTree, ConsoleNode, BaseAddress);
  switch (Status) {
    case RETURN_NOT_FOUND:
    case RETURN_BAD_BUFFER_SIZE:
      return RETURN_PROTOCOL_ERROR;
    case RETURN_SUCCESS:
      return RETURN_SUCCESS;
    default:
      return RETURN_NOT_FOUND;
  }
}
