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