summaryrefslogtreecommitdiffstats
path: root/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
blob: 0a1469550db09d2c9b9c239b894f4b688fa0b165 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/** @file
*
*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
*  Copyright (c) 2014, Linaro Limited. All rights reserved.
*
*  SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/

#include <PiPei.h>

#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/PcdLib.h>
#include <libfdt.h>

#include <Guid/EarlyPL011BaseAddress.h>
#include <Guid/FdtHob.h>

EFI_STATUS
EFIAPI
PlatformPeim (
  VOID
  )
{
  VOID               *Base;
  VOID               *NewBase;
  UINTN              FdtSize;
  UINTN              FdtPages;
  UINT64             *FdtHobData;
  UINT64             *UartHobData;
  INT32              Node, Prev;
  CONST CHAR8        *Compatible;
  CONST CHAR8        *CompItem;
  CONST CHAR8        *NodeStatus;
  INT32              Len;
  INT32              StatusLen;
  CONST UINT64       *RegProp;
  UINT64             UartBase;


  Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
  ASSERT (Base != NULL);
  ASSERT (fdt_check_header (Base) == 0);

  FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreeAllocationPadding);
  FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
  NewBase = AllocatePages (FdtPages);
  ASSERT (NewBase != NULL);
  fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));

  FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
  ASSERT (FdtHobData != NULL);
  *FdtHobData = (UINTN)NewBase;

  UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
  ASSERT (UartHobData != NULL);
  *UartHobData = 0;

  //
  // Look for a UART node
  //
  for (Prev = 0;; Prev = Node) {
    Node = fdt_next_node (Base, Prev, NULL);
    if (Node < 0) {
      break;
    }

    //
    // Check for UART node
    //
    Compatible = fdt_getprop (Base, Node, "compatible", &Len);

    //
    // Iterate over the NULL-separated items in the compatible string
    //
    for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
      CompItem += 1 + AsciiStrLen (CompItem)) {

      if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
        NodeStatus = fdt_getprop (Base, Node, "status", &StatusLen);
        if (NodeStatus != NULL && AsciiStrCmp (NodeStatus, "okay") != 0) {
          continue;
        }

        RegProp = fdt_getprop (Base, Node, "reg", &Len);
        ASSERT (Len == 16);

        UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));

        DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));

        *UartHobData = UartBase;
        break;
      }
    }
  }

  BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));

  return EFI_SUCCESS;
}