2 Platform VTd Info Sample PEI driver.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Ppi/VtdInfo.h>
19 #include <Library/PeiServicesLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/PciLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/MemoryAllocationLib.h>
25 #define R_SA_MCHBAR (0x48)
26 #define R_SA_GGC (0x50)
27 #define N_SKL_SA_GGC_GGMS_OFFSET (0x6)
28 #define B_SKL_SA_GGC_GGMS_MASK (0xc0)
29 #define N_SKL_SA_GGC_GMS_OFFSET (0x8)
30 #define B_SKL_SA_GGC_GMS_MASK (0xff00)
31 #define V_SKL_SA_GGC_GGMS_8MB 3
32 #define R_SA_TOLUD (0xbc)
34 #define R_SA_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT for IGD
35 #define R_SA_MCHBAR_VTD2_OFFSET 0x5410 ///< HW UNIT for all other - PEG, USB, SATA etc
37 EFI_GUID gEdkiiSiliconInitializedPpiGuid
= {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
40 EFI_ACPI_DMAR_HEADER DmarHeader
;
42 // VTd engine 1 - integrated graphic
44 EFI_ACPI_DMAR_DRHD_HEADER Drhd1
;
45 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Drhd11
;
46 EFI_ACPI_DMAR_PCI_PATH Drhd111
;
48 // VTd engine 2 - all rest
50 EFI_ACPI_DMAR_DRHD_HEADER Drhd2
;
52 // RMRR 1 - integrated graphic
54 EFI_ACPI_DMAR_RMRR_HEADER Rmrr1
;
55 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Rmrr11
;
56 EFI_ACPI_DMAR_PCI_PATH Rmrr111
;
59 MY_VTD_INFO_PPI mPlatformVTdSample
= {
62 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE
,
63 sizeof(MY_VTD_INFO_PPI
),
64 EFI_ACPI_DMAR_REVISION
,
66 0x26, // HostAddressWidth
71 EFI_ACPI_DMAR_TYPE_DRHD
,
72 sizeof(EFI_ACPI_DMAR_DRHD_HEADER
) +
73 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
) +
74 sizeof(EFI_ACPI_DMAR_PCI_PATH
)
79 0xFED90000 // RegisterBaseAddress -- TO BE PATCHED
82 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT
,
83 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
) +
84 sizeof(EFI_ACPI_DMAR_PCI_PATH
),
96 EFI_ACPI_DMAR_TYPE_DRHD
,
97 sizeof(EFI_ACPI_DMAR_DRHD_HEADER
)
99 EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
, // Flags
102 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
107 EFI_ACPI_DMAR_TYPE_RMRR
,
108 sizeof(EFI_ACPI_DMAR_RMRR_HEADER
) +
109 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
) +
110 sizeof(EFI_ACPI_DMAR_PCI_PATH
)
114 0x0, // ReservedMemoryRegionBaseAddress -- TO BE PATCHED
115 0x0 // ReservedMemoryRegionLimitAddress -- TO BE PATCHED
118 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT
,
119 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
) +
120 sizeof(EFI_ACPI_DMAR_PCI_PATH
),
131 EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc
= {
132 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
133 &gEdkiiVTdInfoPpiGuid
,
138 EFI_ACPI_DMAR_HEADER DmarHeader
;
140 // VTd engine 2 - all rest
142 EFI_ACPI_DMAR_DRHD_HEADER Drhd2
;
143 } MY_VTD_INFO_NO_IGD_PPI
;
145 MY_VTD_INFO_NO_IGD_PPI mPlatformVTdNoIgdSample
= {
148 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE
,
149 sizeof(MY_VTD_INFO_NO_IGD_PPI
),
150 EFI_ACPI_DMAR_REVISION
,
152 0x26, // HostAddressWidth
157 EFI_ACPI_DMAR_TYPE_DRHD
,
158 sizeof(EFI_ACPI_DMAR_DRHD_HEADER
)
160 EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
, // Flags
163 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
167 EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc
= {
168 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
169 &gEdkiiVTdInfoPpiGuid
,
170 &mPlatformVTdNoIgdSample
174 Initialize VTd register.
183 DEBUG ((DEBUG_INFO
, "InitDmar\n"));
185 MchBar
= PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR
)) & ~BIT0
;
186 PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR
), 0xFED10000 | BIT0
);
187 DEBUG ((DEBUG_INFO
, "MchBar - %x\n", MchBar
));
189 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
, (UINT32
)mPlatformVTdSample
.Drhd2
.RegisterBaseAddress
| 1);
190 DEBUG ((DEBUG_INFO
, "VTd2 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
))));
194 Patch Graphic UMA address in RMRR and base address.
196 EFI_PEI_PPI_DESCRIPTOR
*
206 MY_VTD_INFO_PPI
*PlatformVTdSample
;
207 EFI_PEI_PPI_DESCRIPTOR
*PlatformVTdInfoSampleDesc
;
208 MY_VTD_INFO_NO_IGD_PPI
*PlatformVTdNoIgdSample
;
209 EFI_PEI_PPI_DESCRIPTOR
*PlatformVTdNoIgdInfoSampleDesc
;
211 DEBUG ((DEBUG_INFO
, "PatchDmar\n"));
213 if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
214 PlatformVTdSample
= AllocateCopyPool (sizeof(MY_VTD_INFO_PPI
), &mPlatformVTdSample
);
215 ASSERT(PlatformVTdSample
!= NULL
);
216 PlatformVTdInfoSampleDesc
= AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR
), &mPlatformVTdInfoSampleDesc
);
217 ASSERT(PlatformVTdInfoSampleDesc
!= NULL
);
218 PlatformVTdInfoSampleDesc
->Ppi
= PlatformVTdSample
;
221 /// Calculate IGD memsize
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;
224 if (IgdMode
< 0xF0) {
225 IgdMemSize
= IgdMode
* 32 * (1024) * (1024);
227 IgdMemSize
= 4 * (IgdMode
- 0xF0 + 1) * (1024) * (1024);
231 /// Calculate GTT mem size
234 GttMode
= (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC
)) & B_SKL_SA_GGC_GGMS_MASK
) >> N_SKL_SA_GGC_GGMS_OFFSET
;
235 if (GttMode
<= V_SKL_SA_GGC_GGMS_8MB
) {
236 GttMemSize
= (1 << GttMode
) * (1024) * (1024);
239 PlatformVTdSample
->Rmrr1
.ReservedMemoryRegionBaseAddress
= (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD
)) & ~(0x01)) - IgdMemSize
- GttMemSize
;
240 PlatformVTdSample
->Rmrr1
.ReservedMemoryRegionLimitAddress
= PlatformVTdSample
->Rmrr1
.ReservedMemoryRegionBaseAddress
+ IgdMemSize
+ GttMemSize
- 1;
243 /// Update DRHD structures of DmarTable
245 MchBar
= PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR
)) & ~BIT0
;
247 if ((MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
) &~1) != 0) {
248 PlatformVTdSample
->Drhd1
.RegisterBaseAddress
= (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
) &~1);
250 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
, (UINT32
)PlatformVTdSample
->Drhd1
.RegisterBaseAddress
| 1);
252 DEBUG ((DEBUG_INFO
, "VTd1 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD1_OFFSET
))));
254 if ((MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1) != 0) {
255 PlatformVTdSample
->Drhd2
.RegisterBaseAddress
= (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1);
257 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
, (UINT32
)PlatformVTdSample
->Drhd2
.RegisterBaseAddress
| 1);
259 DEBUG ((DEBUG_INFO
, "VTd2 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
))));
261 return PlatformVTdInfoSampleDesc
;
263 PlatformVTdNoIgdSample
= AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI
), &mPlatformVTdNoIgdSample
);
264 ASSERT(PlatformVTdNoIgdSample
!= NULL
);
265 PlatformVTdNoIgdInfoSampleDesc
= AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR
), &mPlatformVTdNoIgdInfoSampleDesc
);
266 ASSERT(PlatformVTdNoIgdInfoSampleDesc
!= NULL
);
267 PlatformVTdNoIgdInfoSampleDesc
->Ppi
= PlatformVTdNoIgdSample
;
270 /// Update DRHD structures of DmarTable
272 MchBar
= PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR
)) & ~BIT0
;
274 if ((MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1) != 0) {
275 PlatformVTdNoIgdSample
->Drhd2
.RegisterBaseAddress
= (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
) &~1);
277 MmioWrite32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
, (UINT32
)PlatformVTdNoIgdSample
->Drhd2
.RegisterBaseAddress
| 1);
279 DEBUG ((DEBUG_INFO
, "VTd2 - %x\n", (MmioRead32 (MchBar
+ R_SA_MCHBAR_VTD2_OFFSET
))));
281 return PlatformVTdNoIgdInfoSampleDesc
;
286 The callback function for SiliconInitializedPpi.
287 It reinstalls VTD_INFO_PPI.
289 @param[in] PeiServices General purpose services available to every PEIM.
290 @param[in] NotifyDescriptor Notify that this module published.
291 @param[in] Ppi PPI that was installed.
293 @retval EFI_SUCCESS The function completed successfully.
297 SiliconInitializedPpiNotifyCallback (
298 IN CONST EFI_PEI_SERVICES
**PeiServices
,
299 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
304 EFI_PEI_PPI_DESCRIPTOR
*PpiDesc
;
306 PpiDesc
= PatchDmar ();
308 Status
= PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc
, PpiDesc
);
309 ASSERT_EFI_ERROR (Status
);
313 EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList
= {
314 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
315 &gEdkiiSiliconInitializedPpiGuid
,
316 (EFI_PEIM_NOTIFY_ENTRY_POINT
) SiliconInitializedPpiNotifyCallback
320 Platform VTd Info sample driver.
322 @param[in] FileHandle Handle of the file being invoked.
323 @param[in] PeiServices Describes the list of possible PEI Services.
325 @retval EFI_SUCCESS if it completed successfully.
329 PlatformVTdInfoSampleInitialize (
330 IN EFI_PEI_FILE_HANDLE FileHandle
,
331 IN CONST EFI_PEI_SERVICES
**PeiServices
335 BOOLEAN SiliconInitialized
;
336 VOID
*SiliconInitializedPpi
;
337 EFI_PEI_PPI_DESCRIPTOR
*PpiDesc
;
339 SiliconInitialized
= FALSE
;
341 // Check if silicon is initialized.
343 Status
= PeiServicesLocatePpi (
344 &gEdkiiSiliconInitializedPpiGuid
,
347 &SiliconInitializedPpi
349 if (!EFI_ERROR(Status
)) {
350 SiliconInitialized
= TRUE
;
352 DEBUG ((DEBUG_INFO
, "SiliconInitialized - %x\n", SiliconInitialized
));
353 if (!SiliconInitialized
) {
354 Status
= PeiServicesNotifyPpi (&mSiliconInitializedNotifyList
);
357 Status
= PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc
);
358 ASSERT_EFI_ERROR (Status
);
360 PpiDesc
= PatchDmar ();
362 Status
= PeiServicesInstallPpi (PpiDesc
);
363 ASSERT_EFI_ERROR (Status
);