]> git.proxmox.com Git - mirror_edk2.git/blob - ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
ArmVirtPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmVirtPkg / Library / PlatformPeiLib / PlatformPeiLib.c
1 /** @file
2 *
3 * Copyright (c) 2011-2014, ARM Limited. All rights reserved.
4 * Copyright (c) 2014-2020, Linaro Limited. All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
7 *
8 **/
9
10 #include <PiPei.h>
11
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/HobLib.h>
15 #include <Library/PcdLib.h>
16 #include <Library/PeiServicesLib.h>
17 #include <libfdt.h>
18
19 #include <Guid/EarlyPL011BaseAddress.h>
20 #include <Guid/FdtHob.h>
21
22 STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpm2DiscoveredPpi = {
23 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
24 &gOvmfTpmDiscoveredPpiGuid,
25 NULL
26 };
27
28 STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpm2InitializationDonePpi = {
29 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
30 &gPeiTpmInitializationDonePpiGuid,
31 NULL
32 };
33
34 EFI_STATUS
35 EFIAPI
36 PlatformPeim (
37 VOID
38 )
39 {
40 VOID *Base;
41 VOID *NewBase;
42 UINTN FdtSize;
43 UINTN FdtPages;
44 UINT64 *FdtHobData;
45 UINT64 *UartHobData;
46 INT32 Node, Prev;
47 INT32 Parent, Depth;
48 CONST CHAR8 *Compatible;
49 CONST CHAR8 *CompItem;
50 CONST CHAR8 *NodeStatus;
51 INT32 Len;
52 INT32 RangesLen;
53 INT32 StatusLen;
54 CONST UINT64 *RegProp;
55 CONST UINT32 *RangesProp;
56 UINT64 UartBase;
57 UINT64 TpmBase;
58 EFI_STATUS Status;
59
60 Base = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
61 ASSERT (Base != NULL);
62 ASSERT (fdt_check_header (Base) == 0);
63
64 FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreeAllocationPadding);
65 FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
66 NewBase = AllocatePages (FdtPages);
67 ASSERT (NewBase != NULL);
68 fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
69
70 FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
71 ASSERT (FdtHobData != NULL);
72 *FdtHobData = (UINTN)NewBase;
73
74 UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
75 ASSERT (UartHobData != NULL);
76 *UartHobData = 0;
77
78 TpmBase = 0;
79
80 //
81 // Set Parent to suppress incorrect compiler/analyzer warnings.
82 //
83 Parent = 0;
84
85 for (Prev = Depth = 0; ; Prev = Node) {
86 Node = fdt_next_node (Base, Prev, &Depth);
87 if (Node < 0) {
88 break;
89 }
90
91 if (Depth == 1) {
92 Parent = Node;
93 }
94
95 Compatible = fdt_getprop (Base, Node, "compatible", &Len);
96
97 //
98 // Iterate over the NULL-separated items in the compatible string
99 //
100 for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
101 CompItem += 1 + AsciiStrLen (CompItem))
102 {
103 if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
104 NodeStatus = fdt_getprop (Base, Node, "status", &StatusLen);
105 if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
106 continue;
107 }
108
109 RegProp = fdt_getprop (Base, Node, "reg", &Len);
110 ASSERT (Len == 16);
111
112 UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
113
114 DEBUG ((DEBUG_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
115
116 *UartHobData = UartBase;
117 break;
118 } else if (FeaturePcdGet (PcdTpm2SupportEnabled) &&
119 (AsciiStrCmp (CompItem, "tcg,tpm-tis-mmio") == 0))
120 {
121 RegProp = fdt_getprop (Base, Node, "reg", &Len);
122 ASSERT (Len == 8 || Len == 16);
123 if (Len == 8) {
124 TpmBase = fdt32_to_cpu (RegProp[0]);
125 } else if (Len == 16) {
126 TpmBase = fdt64_to_cpu (ReadUnaligned64 ((UINT64 *)RegProp));
127 }
128
129 if (Depth > 1) {
130 //
131 // QEMU/mach-virt may put the TPM on the platform bus, in which case
132 // we have to take its 'ranges' property into account to translate the
133 // MMIO address. This consists of a <child base, parent base, size>
134 // tuple, where the child base and the size use the same number of
135 // cells as the 'reg' property above, and the parent base uses 2 cells
136 //
137 RangesProp = fdt_getprop (Base, Parent, "ranges", &RangesLen);
138 ASSERT (RangesProp != NULL);
139
140 //
141 // a plain 'ranges' attribute without a value implies a 1:1 mapping
142 //
143 if (RangesLen != 0) {
144 //
145 // assume a single translated range with 2 cells for the parent base
146 //
147 if (RangesLen != Len + 2 * sizeof (UINT32)) {
148 DEBUG ((
149 DEBUG_WARN,
150 "%a: 'ranges' property has unexpected size %d\n",
151 __FUNCTION__,
152 RangesLen
153 ));
154 break;
155 }
156
157 if (Len == 8) {
158 TpmBase -= fdt32_to_cpu (RangesProp[0]);
159 } else {
160 TpmBase -= fdt64_to_cpu (ReadUnaligned64 ((UINT64 *)RangesProp));
161 }
162
163 //
164 // advance RangesProp to the parent bus address
165 //
166 RangesProp = (UINT32 *)((UINT8 *)RangesProp + Len / 2);
167 TpmBase += fdt64_to_cpu (ReadUnaligned64 ((UINT64 *)RangesProp));
168 }
169 }
170
171 break;
172 }
173 }
174 }
175
176 if (FeaturePcdGet (PcdTpm2SupportEnabled)) {
177 if (TpmBase != 0) {
178 DEBUG ((DEBUG_INFO, "%a: TPM @ 0x%lx\n", __FUNCTION__, TpmBase));
179
180 Status = (EFI_STATUS)PcdSet64S (PcdTpmBaseAddress, TpmBase);
181 ASSERT_EFI_ERROR (Status);
182
183 Status = PeiServicesInstallPpi (&mTpm2DiscoveredPpi);
184 } else {
185 Status = PeiServicesInstallPpi (&mTpm2InitializationDonePpi);
186 }
187
188 ASSERT_EFI_ERROR (Status);
189 }
190
191 BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
192
193 return EFI_SUCCESS;
194 }