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