2 Platform VTd Info Sample PEI driver.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Ppi/VtdInfo.h>
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>
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)
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
31 EFI_GUID gEdkiiSiliconInitializedPpiGuid
= {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
34 EFI_ACPI_DMAR_HEADER DmarHeader
;
36 // VTd engine 1 - integrated graphic
38 EFI_ACPI_DMAR_DRHD_HEADER Drhd1
;
39 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Drhd11
;
40 EFI_ACPI_DMAR_PCI_PATH Drhd111
;
42 // VTd engine 2 - all rest
44 EFI_ACPI_DMAR_DRHD_HEADER Drhd2
;
46 // RMRR 1 - integrated graphic
48 EFI_ACPI_DMAR_RMRR_HEADER Rmrr1
;
49 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Rmrr11
;
50 EFI_ACPI_DMAR_PCI_PATH Rmrr111
;
53 MY_VTD_INFO_PPI mPlatformVTdSample
= {
56 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE
,
57 sizeof(MY_VTD_INFO_PPI
),
58 EFI_ACPI_DMAR_REVISION
,
60 0x26, // HostAddressWidth
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
)
73 0xFED90000 // RegisterBaseAddress -- TO BE PATCHED
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
),
90 EFI_ACPI_DMAR_TYPE_DRHD
,
91 sizeof(EFI_ACPI_DMAR_DRHD_HEADER
)
93 EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
, // Flags
96 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
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
)
108 0x0, // ReservedMemoryRegionBaseAddress -- TO BE PATCHED
109 0x0 // ReservedMemoryRegionLimitAddress -- TO BE PATCHED
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
),
125 EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc
= {
126 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
127 &gEdkiiVTdInfoPpiGuid
,
132 EFI_ACPI_DMAR_HEADER DmarHeader
;
134 // VTd engine 2 - all rest
136 EFI_ACPI_DMAR_DRHD_HEADER Drhd2
;
137 } MY_VTD_INFO_NO_IGD_PPI
;
139 MY_VTD_INFO_NO_IGD_PPI mPlatformVTdNoIgdSample
= {
142 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE
,
143 sizeof(MY_VTD_INFO_NO_IGD_PPI
),
144 EFI_ACPI_DMAR_REVISION
,
146 0x26, // HostAddressWidth
151 EFI_ACPI_DMAR_TYPE_DRHD
,
152 sizeof(EFI_ACPI_DMAR_DRHD_HEADER
)
154 EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
, // Flags
157 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
161 EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc
= {
162 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
163 &gEdkiiVTdInfoPpiGuid
,
164 &mPlatformVTdNoIgdSample
168 Initialize VTd register.
177 DEBUG ((DEBUG_INFO
, "InitDmar\n"));
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
));
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
))));
188 Patch Graphic UMA address in RMRR and base address.
190 EFI_PEI_PPI_DESCRIPTOR
*
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
;
205 DEBUG ((DEBUG_INFO
, "PatchDmar\n"));
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
;
215 /// Calculate IGD memsize
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);
221 IgdMemSize
= 4 * (IgdMode
- 0xF0 + 1) * (1024) * (1024);
225 /// Calculate GTT mem size
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);
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;
237 /// Update DRHD structures of DmarTable
239 MchBar
= PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR
)) & ~BIT0
;
241 if ((MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
) &~1) != 0) {
242 PlatformVTdSample
->Drhd1
.RegisterBaseAddress
= (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
) &~1);
244 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
, (UINT32
)PlatformVTdSample
->Drhd1
.RegisterBaseAddress
| 1);
246 DEBUG ((DEBUG_INFO
, "VTd1 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
))));
248 if ((MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1) != 0) {
249 PlatformVTdSample
->Drhd2
.RegisterBaseAddress
= (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1);
251 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
, (UINT32
)PlatformVTdSample
->Drhd2
.RegisterBaseAddress
| 1);
253 DEBUG ((DEBUG_INFO
, "VTd2 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
))));
255 return PlatformVTdInfoSampleDesc
;
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
;
264 /// Update DRHD structures of DmarTable
266 MchBar
= PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR
)) & ~BIT0
;
268 if ((MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1) != 0) {
269 PlatformVTdNoIgdSample
->Drhd2
.RegisterBaseAddress
= (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1);
271 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
, (UINT32
)PlatformVTdNoIgdSample
->Drhd2
.RegisterBaseAddress
| 1);
273 DEBUG ((DEBUG_INFO
, "VTd2 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
))));
275 return PlatformVTdNoIgdInfoSampleDesc
;
280 The callback function for SiliconInitializedPpi.
281 It reinstalls VTD_INFO_PPI.
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.
287 @retval EFI_SUCCESS The function completed successfully.
291 SiliconInitializedPpiNotifyCallback (
292 IN CONST EFI_PEI_SERVICES
**PeiServices
,
293 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
298 EFI_PEI_PPI_DESCRIPTOR
*PpiDesc
;
300 PpiDesc
= PatchDmar ();
302 Status
= PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc
, PpiDesc
);
303 ASSERT_EFI_ERROR (Status
);
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
314 Platform VTd Info sample driver.
316 @param[in] FileHandle Handle of the file being invoked.
317 @param[in] PeiServices Describes the list of possible PEI Services.
319 @retval EFI_SUCCESS if it completed successfully.
323 PlatformVTdInfoSampleInitialize (
324 IN EFI_PEI_FILE_HANDLE FileHandle
,
325 IN CONST EFI_PEI_SERVICES
**PeiServices
329 BOOLEAN SiliconInitialized
;
330 VOID
*SiliconInitializedPpi
;
331 EFI_PEI_PPI_DESCRIPTOR
*PpiDesc
;
333 SiliconInitialized
= FALSE
;
335 // Check if silicon is initialized.
337 Status
= PeiServicesLocatePpi (
338 &gEdkiiSiliconInitializedPpiGuid
,
341 &SiliconInitializedPpi
343 if (!EFI_ERROR(Status
)) {
344 SiliconInitialized
= TRUE
;
346 DEBUG ((DEBUG_INFO
, "SiliconInitialized - %x\n", SiliconInitialized
));
347 if (!SiliconInitialized
) {
348 Status
= PeiServicesNotifyPpi (&mSiliconInitializedNotifyList
);
351 Status
= PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc
);
352 ASSERT_EFI_ERROR (Status
);
354 PpiDesc
= PatchDmar ();
356 Status
= PeiServicesInstallPpi (PpiDesc
);
357 ASSERT_EFI_ERROR (Status
);