IntelSiliconPkg/VtdPeiSample: Add premem support.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / PlatformVTdInfoSamplePei / PlatformVTdInfoSamplePei.c
CommitLineData
53269009
JY
1/** @file\r
2 Platform VTd Info Sample PEI driver.\r
3\r
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiPei.h>\r
16\r
4084ccfa 17#include <Ppi/VtdInfo.h>\r
53269009
JY
18\r
19#include <Library/PeiServicesLib.h>\r
20#include <Library/DebugLib.h>\r
70dc3ec5
JY
21#include <Library/PciLib.h>\r
22#include <Library/IoLib.h>\r
af807bb9 23#include <Library/MemoryAllocationLib.h>\r
70dc3ec5
JY
24\r
25#define R_SA_MCHBAR (0x48)\r
26#define R_SA_GGC (0x50)\r
27#define N_SKL_SA_GGC_GGMS_OFFSET (0x6)\r
28#define B_SKL_SA_GGC_GGMS_MASK (0xc0)\r
29#define N_SKL_SA_GGC_GMS_OFFSET (0x8)\r
30#define B_SKL_SA_GGC_GMS_MASK (0xff00)\r
31#define V_SKL_SA_GGC_GGMS_8MB 3\r
32#define R_SA_TOLUD (0xbc)\r
33\r
34#define R_SA_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT for IGD\r
35#define R_SA_MCHBAR_VTD2_OFFSET 0x5410 ///< HW UNIT for all other - PEG, USB, SATA etc\r
53269009 36\r
af807bb9
JY
37EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};\r
38\r
53269009 39typedef struct {\r
70dc3ec5
JY
40 EFI_ACPI_DMAR_HEADER DmarHeader;\r
41 //\r
42 // VTd engine 1 - integrated graphic\r
43 //\r
44 EFI_ACPI_DMAR_DRHD_HEADER Drhd1;\r
45 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Drhd11;\r
46 EFI_ACPI_DMAR_PCI_PATH Drhd111;\r
47 //\r
48 // VTd engine 2 - all rest\r
49 //\r
50 EFI_ACPI_DMAR_DRHD_HEADER Drhd2;\r
51 //\r
52 // RMRR 1 - integrated graphic\r
53 //\r
54 EFI_ACPI_DMAR_RMRR_HEADER Rmrr1;\r
55 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Rmrr11;\r
56 EFI_ACPI_DMAR_PCI_PATH Rmrr111;\r
53269009
JY
57} MY_VTD_INFO_PPI;\r
58\r
59MY_VTD_INFO_PPI mPlatformVTdSample = {\r
70dc3ec5
JY
60 { // DmarHeader\r
61 { // Header\r
62 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,\r
63 sizeof(MY_VTD_INFO_PPI),\r
64 EFI_ACPI_DMAR_REVISION,\r
65 },\r
66 0x26, // HostAddressWidth\r
67 },\r
68\r
69 { // Drhd1\r
70 { // Header\r
71 EFI_ACPI_DMAR_TYPE_DRHD,\r
72 sizeof(EFI_ACPI_DMAR_DRHD_HEADER) +\r
73 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +\r
74 sizeof(EFI_ACPI_DMAR_PCI_PATH)\r
75 },\r
76 0, // Flags\r
77 0, // Reserved\r
78 0, // SegmentNumber\r
79 0xFED90000 // RegisterBaseAddress -- TO BE PATCHED\r
80 },\r
81 { // Drhd11\r
82 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT,\r
83 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +\r
84 sizeof(EFI_ACPI_DMAR_PCI_PATH),\r
85 0, // Reserved2\r
86 0, // EnumerationId\r
87 0 // StartBusNumber\r
88 },\r
89 { // Drhd111\r
90 2, // Device\r
91 0 // Function\r
92 },\r
93\r
94 { // Drhd2\r
95 { // Header\r
96 EFI_ACPI_DMAR_TYPE_DRHD,\r
97 sizeof(EFI_ACPI_DMAR_DRHD_HEADER)\r
98 },\r
99 EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags\r
100 0, // Reserved\r
101 0, // SegmentNumber\r
102 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED\r
103 },\r
104\r
105 { // Rmrr1\r
106 { // Header\r
107 EFI_ACPI_DMAR_TYPE_RMRR,\r
108 sizeof(EFI_ACPI_DMAR_RMRR_HEADER) +\r
109 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +\r
110 sizeof(EFI_ACPI_DMAR_PCI_PATH)\r
111 },\r
112 {0}, // Reserved\r
113 0, // SegmentNumber\r
114 0x0, // ReservedMemoryRegionBaseAddress -- TO BE PATCHED\r
115 0x0 // ReservedMemoryRegionLimitAddress -- TO BE PATCHED\r
116 },\r
117 { // Rmrr11\r
118 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT,\r
119 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +\r
120 sizeof(EFI_ACPI_DMAR_PCI_PATH),\r
121 0, // Reserved2\r
122 0, // EnumerationId\r
123 0 // StartBusNumber\r
124 },\r
125 { // Rmrr111\r
126 2, // Device\r
127 0 // Function\r
128 },\r
53269009
JY
129};\r
130\r
131EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {\r
132 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
133 &gEdkiiVTdInfoPpiGuid,\r
134 &mPlatformVTdSample\r
135};\r
136\r
af807bb9
JY
137typedef struct {\r
138 EFI_ACPI_DMAR_HEADER DmarHeader;\r
139 //\r
140 // VTd engine 2 - all rest\r
141 //\r
142 EFI_ACPI_DMAR_DRHD_HEADER Drhd2;\r
143} MY_VTD_INFO_NO_IGD_PPI;\r
144\r
145MY_VTD_INFO_NO_IGD_PPI mPlatformVTdNoIgdSample = {\r
146 { // DmarHeader\r
147 { // Header\r
148 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,\r
149 sizeof(MY_VTD_INFO_NO_IGD_PPI),\r
150 EFI_ACPI_DMAR_REVISION,\r
151 },\r
152 0x26, // HostAddressWidth\r
153 },\r
154\r
155 { // Drhd2\r
156 { // Header\r
157 EFI_ACPI_DMAR_TYPE_DRHD,\r
158 sizeof(EFI_ACPI_DMAR_DRHD_HEADER)\r
159 },\r
160 EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags\r
161 0, // Reserved\r
162 0, // SegmentNumber\r
163 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED\r
164 },\r
165};\r
166\r
167EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {\r
168 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
169 &gEdkiiVTdInfoPpiGuid,\r
170 &mPlatformVTdNoIgdSample\r
171};\r
172\r
70dc3ec5 173/**\r
af807bb9 174 Initialize VTd register.\r
70dc3ec5
JY
175**/\r
176VOID\r
af807bb9 177InitDmar (\r
70dc3ec5
JY
178 VOID\r
179 )\r
180{\r
181 UINT32 MchBar;\r
af807bb9
JY
182\r
183 DEBUG ((DEBUG_INFO, "InitDmar\n"));\r
184\r
185 MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;\r
186 PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | BIT0);\r
187 DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));\r
188\r
189 MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);\r
190 DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));\r
191}\r
192\r
193/**\r
194 Patch Graphic UMA address in RMRR and base address.\r
195**/\r
196EFI_PEI_PPI_DESCRIPTOR *\r
197PatchDmar (\r
198 VOID\r
199 )\r
200{\r
201 UINT32 MchBar;\r
202 UINT16 IgdMode;\r
203 UINT16 GttMode;\r
204 UINT32 IgdMemSize;\r
205 UINT32 GttMemSize;\r
206 MY_VTD_INFO_PPI *PlatformVTdSample;\r
207 EFI_PEI_PPI_DESCRIPTOR *PlatformVTdInfoSampleDesc;\r
208 MY_VTD_INFO_NO_IGD_PPI *PlatformVTdNoIgdSample;\r
209 EFI_PEI_PPI_DESCRIPTOR *PlatformVTdNoIgdInfoSampleDesc;\r
210\r
211 DEBUG ((DEBUG_INFO, "PatchDmar\n"));\r
212\r
213 if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {\r
214 PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);\r
215 ASSERT(PlatformVTdSample != NULL);\r
216 PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);\r
217 ASSERT(PlatformVTdInfoSampleDesc != NULL);\r
218 PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;\r
219\r
220 ///\r
221 /// Calculate IGD memsize\r
222 ///\r
223 IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;\r
224 if (IgdMode < 0xF0) {\r
225 IgdMemSize = IgdMode * 32 * (1024) * (1024);\r
226 } else {\r
227 IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);\r
228 }\r
229\r
230 ///\r
231 /// Calculate GTT mem size\r
232 ///\r
233 GttMemSize = 0;\r
234 GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;\r
235 if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {\r
236 GttMemSize = (1 << GttMode) * (1024) * (1024);\r
237 }\r
238\r
239 PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;\r
240 PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress = PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;\r
241\r
242 ///\r
243 /// Update DRHD structures of DmarTable\r
244 ///\r
245 MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;\r
246\r
247 if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {\r
248 PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);\r
249 } else {\r
250 MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);\r
251 }\r
252 DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));\r
253\r
254 if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {\r
255 PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);\r
256 } else {\r
257 MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);\r
258 }\r
259 DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));\r
260\r
261 return PlatformVTdInfoSampleDesc;\r
70dc3ec5 262 } else {\r
af807bb9
JY
263 PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);\r
264 ASSERT(PlatformVTdNoIgdSample != NULL);\r
265 PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);\r
266 ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);\r
267 PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;\r
268\r
269 ///\r
270 /// Update DRHD structures of DmarTable\r
271 ///\r
272 MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;\r
70dc3ec5 273\r
af807bb9
JY
274 if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {\r
275 PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);\r
276 } else {\r
277 MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);\r
278 }\r
279 DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));\r
280\r
281 return PlatformVTdNoIgdInfoSampleDesc;\r
70dc3ec5 282 }\r
af807bb9 283}\r
70dc3ec5 284\r
af807bb9
JY
285/**\r
286 The callback function for SiliconInitializedPpi.\r
287 It reinstalls VTD_INFO_PPI.\r
70dc3ec5 288\r
af807bb9
JY
289 @param[in] PeiServices General purpose services available to every PEIM.\r
290 @param[in] NotifyDescriptor Notify that this module published.\r
291 @param[in] Ppi PPI that was installed.\r
292\r
293 @retval EFI_SUCCESS The function completed successfully.\r
294**/\r
295EFI_STATUS\r
296EFIAPI\r
297SiliconInitializedPpiNotifyCallback (\r
298 IN CONST EFI_PEI_SERVICES **PeiServices,\r
299 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
300 IN VOID *Ppi\r
301 )\r
302{\r
303 EFI_STATUS Status;\r
304 EFI_PEI_PPI_DESCRIPTOR *PpiDesc;\r
305\r
306 PpiDesc = PatchDmar ();\r
307\r
308 Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, PpiDesc);\r
309 ASSERT_EFI_ERROR (Status);\r
310 return EFI_SUCCESS;\r
70dc3ec5
JY
311}\r
312\r
af807bb9
JY
313EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {\r
314 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
315 &gEdkiiSiliconInitializedPpiGuid,\r
316 (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback\r
317};\r
318\r
53269009
JY
319/**\r
320 Platform VTd Info sample driver.\r
321\r
322 @param[in] FileHandle Handle of the file being invoked.\r
323 @param[in] PeiServices Describes the list of possible PEI Services.\r
324\r
325 @retval EFI_SUCCESS if it completed successfully.\r
326**/\r
327EFI_STATUS\r
328EFIAPI\r
329PlatformVTdInfoSampleInitialize (\r
330 IN EFI_PEI_FILE_HANDLE FileHandle,\r
331 IN CONST EFI_PEI_SERVICES **PeiServices\r
332 )\r
333{\r
af807bb9
JY
334 EFI_STATUS Status;\r
335 BOOLEAN SiliconInitialized;\r
336 VOID *SiliconInitializedPpi;\r
337 EFI_PEI_PPI_DESCRIPTOR *PpiDesc;\r
338\r
339 SiliconInitialized = FALSE;\r
340 //\r
341 // Check if silicon is initialized.\r
342 //\r
343 Status = PeiServicesLocatePpi (\r
344 &gEdkiiSiliconInitializedPpiGuid,\r
345 0,\r
346 NULL,\r
347 &SiliconInitializedPpi\r
348 );\r
349 if (!EFI_ERROR(Status)) {\r
350 SiliconInitialized = TRUE;\r
351 }\r
352 DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", SiliconInitialized));\r
353 if (!SiliconInitialized) {\r
354 Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);\r
355 InitDmar ();\r
53269009 356\r
af807bb9
JY
357 Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);\r
358 ASSERT_EFI_ERROR (Status);\r
359 } else {\r
360 PpiDesc = PatchDmar ();\r
70dc3ec5 361\r
af807bb9
JY
362 Status = PeiServicesInstallPpi (PpiDesc);\r
363 ASSERT_EFI_ERROR (Status);\r
364 }\r
53269009
JY
365\r
366 return Status;\r
367}\r